From 9af6789314a01af17924b1c0ee06ac5d66016e00 Mon Sep 17 00:00:00 2001 From: librelois <c@elo.tf> Date: Thu, 22 Apr 2021 21:28:12 +0200 Subject: [PATCH] [chore] move most of rust code in repos duniter-core & duniter-gva --- Cargo.lock | 1820 ++++------------- Cargo.toml | 15 - deny.toml | 1 - neon/native/Cargo.toml | 2 +- rust-bins/duniter-dbex/Cargo.toml | 7 +- rust-bins/duniter-dbex/src/export_bc.rs | 2 +- rust-bins/duniter-dbex/src/main.rs | 12 +- rust-bins/duniter-dbex/src/migrate.rs | 6 +- rust-libs/dubp-wot/Cargo.toml | 23 - rust-libs/dubp-wot/README.md | 10 - rust-libs/dubp-wot/src/data/mod.rs | 196 -- rust-libs/dubp-wot/src/data/rusty.rs | 258 --- rust-libs/dubp-wot/src/lib.rs | 561 ----- .../dubp-wot/src/operations/centrality.rs | 192 -- rust-libs/dubp-wot/src/operations/density.rs | 31 - rust-libs/dubp-wot/src/operations/distance.rs | 211 -- rust-libs/dubp-wot/src/operations/mod.rs | 21 - rust-libs/dubp-wot/src/operations/path.rs | 107 - rust-libs/dubp-wot/tests/g1_genesis.bin | Bin 3223 -> 0 bytes rust-libs/dubp-wot/tests/g1_genesis.bin.gz | Bin 917 -> 0 bytes rust-libs/duniter-bc-reader/Cargo.toml | 21 - rust-libs/duniter-bc-reader/src/lib.rs | 30 - rust-libs/duniter-conf/Cargo.toml | 10 - rust-libs/duniter-conf/src/gva_conf.rs | 113 - rust-libs/duniter-conf/src/lib.rs | 54 - rust-libs/duniter-dbs-write-ops/Cargo.toml | 35 - .../duniter-dbs-write-ops/src/apply_block.rs | 173 -- rust-libs/duniter-dbs-write-ops/src/bc.rs | 325 --- .../src/bc/identities.rs | 95 - rust-libs/duniter-dbs-write-ops/src/bc/txs.rs | 130 -- rust-libs/duniter-dbs-write-ops/src/bc/uds.rs | 69 - rust-libs/duniter-dbs-write-ops/src/cm.rs | 51 - rust-libs/duniter-dbs-write-ops/src/lib.rs | 55 - rust-libs/duniter-dbs-write-ops/src/txs_mp.rs | 225 -- rust-libs/duniter-dbs/Cargo.toml | 48 - rust-libs/duniter-dbs/src/databases.rs | 20 - rust-libs/duniter-dbs/src/databases/bc_v1.rs | 158 -- rust-libs/duniter-dbs/src/databases/bc_v2.rs | 30 - rust-libs/duniter-dbs/src/databases/cm_v1.rs | 18 - .../duniter-dbs/src/databases/network_v1.rs | 24 - .../duniter-dbs/src/databases/txs_mp_v2.rs | 29 - rust-libs/duniter-dbs/src/keys.rs | 28 - rust-libs/duniter-dbs/src/keys/all.rs | 57 - .../duniter-dbs/src/keys/block_number.rs | 72 - rust-libs/duniter-dbs/src/keys/blockstamp.rs | 100 - .../duniter-dbs/src/keys/dunp_node_id.rs | 111 - rust-libs/duniter-dbs/src/keys/hash.rs | 106 - rust-libs/duniter-dbs/src/keys/pubkey.rs | 117 -- .../duniter-dbs/src/keys/pubkey_and_sig.rs | 69 - rust-libs/duniter-dbs/src/keys/source_key.rs | 93 - rust-libs/duniter-dbs/src/keys/timestamp.rs | 56 - rust-libs/duniter-dbs/src/keys/ud_id.rs | 123 -- rust-libs/duniter-dbs/src/keys/uid.rs | 65 - rust-libs/duniter-dbs/src/keys/utxo_id.rs | 124 -- .../duniter-dbs/src/keys/wallet_conditions.rs | 112 - rust-libs/duniter-dbs/src/lib.rs | 144 -- rust-libs/duniter-dbs/src/open_dbs.rs | 109 - rust-libs/duniter-dbs/src/values.rs | 35 - rust-libs/duniter-dbs/src/values/block_db.rs | 152 -- .../duniter-dbs/src/values/block_head_db.rs | 85 - .../duniter-dbs/src/values/block_meta.rs | 133 -- .../src/values/block_number_array_db.rs | 53 - rust-libs/duniter-dbs/src/values/cindex_db.rs | 98 - rust-libs/duniter-dbs/src/values/dunp_head.rs | 124 -- rust-libs/duniter-dbs/src/values/idty_db.rs | 52 - rust-libs/duniter-dbs/src/values/iindex_db.rs | 81 - rust-libs/duniter-dbs/src/values/kick_db.rs | 55 - rust-libs/duniter-dbs/src/values/mindex_db.rs | 105 - rust-libs/duniter-dbs/src/values/peer_card.rs | 58 - rust-libs/duniter-dbs/src/values/pubkey_db.rs | 149 -- rust-libs/duniter-dbs/src/values/sindex_db.rs | 123 -- .../duniter-dbs/src/values/source_amount.rs | 67 - rust-libs/duniter-dbs/src/values/tx_db.rs | 51 - rust-libs/duniter-dbs/src/values/txs.rs | 51 - .../duniter-dbs/src/values/ud_entry_db.rs | 79 - rust-libs/duniter-dbs/src/values/utxo.rs | 159 -- rust-libs/duniter-dbs/src/values/wallet_db.rs | 55 - .../src/values/wallet_script_with_sa.rs | 52 - rust-libs/duniter-dbs/tests/test_explorer.rs | 253 --- .../duniter-dbs/tests/test_read_write.rs | 405 ---- rust-libs/duniter-dbs/tests/test_tmp_real.rs | 767 ------- rust-libs/duniter-global/Cargo.toml | 18 - rust-libs/duniter-global/src/lib.rs | 155 -- rust-libs/duniter-mempools/Cargo.toml | 22 - rust-libs/duniter-mempools/src/lib.rs | 133 -- rust-libs/duniter-module/Cargo.toml | 22 - rust-libs/duniter-module/src/lib.rs | 344 ---- rust-libs/duniter-server/Cargo.toml | 12 +- rust-libs/duniter-server/src/fill_cm.rs | 4 +- .../src/legacy/block_indexer.rs | 8 +- rust-libs/duniter-server/src/legacy/dunp.rs | 25 +- .../duniter-server/src/legacy/txs_mempool.rs | 10 +- rust-libs/duniter-server/src/lib.rs | 32 +- rust-libs/modules/gva/Cargo.toml | 42 - rust-libs/modules/gva/bca/Cargo.toml | 33 - .../modules/gva/bca/src/exec_req_type.rs | 99 - .../gva/bca/src/exec_req_type/balances.rs | 61 - .../gva/bca/src/exec_req_type/current_ud.rs | 30 - .../last_blockstamp_out_of_fork_window.rs | 99 - .../bca/src/exec_req_type/members_count.rs | 52 - .../exec_req_type/prepare_simple_payment.rs | 223 -- .../gva/bca/src/exec_req_type/send_txs.rs | 63 - .../gva/bca/src/exec_req_type/utxos.rs | 58 - rust-libs/modules/gva/bca/src/lib.rs | 412 ---- rust-libs/modules/gva/bca/types/Cargo.toml | 20 - rust-libs/modules/gva/bca/types/src/amount.rs | 46 - .../modules/gva/bca/types/src/identity.rs | 22 - rust-libs/modules/gva/bca/types/src/lib.rs | 144 -- .../gva/bca/types/src/prepare_payment.rs | 32 - .../modules/gva/bca/types/src/rejected_tx.rs | 30 - rust-libs/modules/gva/bca/types/src/utxo.rs | 23 - rust-libs/modules/gva/db/Cargo.toml | 32 - rust-libs/modules/gva/db/src/keys.rs | 17 - .../modules/gva/db/src/keys/gva_utxo_id.rs | 166 -- .../gva/db/src/keys/wallet_hash_with_bn.rs | 119 -- rust-libs/modules/gva/db/src/lib.rs | 71 - rust-libs/modules/gva/db/src/values.rs | 18 - .../modules/gva/db/src/values/gva_idty_db.rs | 54 - rust-libs/modules/gva/db/src/values/gva_tx.rs | 56 - .../gva/db/src/values/wallet_script_array.rs | 53 - rust-libs/modules/gva/dbs-reader/Cargo.toml | 31 - rust-libs/modules/gva/dbs-reader/src/block.rs | 228 --- .../gva/dbs-reader/src/current_frame.rs | 33 - .../modules/gva/dbs-reader/src/find_inputs.rs | 241 --- rust-libs/modules/gva/dbs-reader/src/idty.rs | 70 - rust-libs/modules/gva/dbs-reader/src/lib.rs | 341 --- .../modules/gva/dbs-reader/src/network.rs | 200 -- .../modules/gva/dbs-reader/src/pagination.rs | 144 -- .../modules/gva/dbs-reader/src/txs_history.rs | 836 -------- .../gva/dbs-reader/src/uds_of_pubkey.rs | 829 -------- rust-libs/modules/gva/dbs-reader/src/utxos.rs | 500 ----- rust-libs/modules/gva/gql/Cargo.toml | 37 - rust-libs/modules/gva/gql/src/entities.rs | 112 - .../modules/gva/gql/src/entities/block_gva.rs | 176 -- .../modules/gva/gql/src/entities/idty_gva.rs | 20 - .../modules/gva/gql/src/entities/network.rs | 74 - .../modules/gva/gql/src/entities/tx_gva.rs | 84 - .../modules/gva/gql/src/entities/ud_gva.rs | 48 - .../modules/gva/gql/src/entities/utxos_gva.rs | 42 - rust-libs/modules/gva/gql/src/inputs.rs | 57 - .../modules/gva/gql/src/inputs_validators.rs | 36 - rust-libs/modules/gva/gql/src/lib.rs | 157 -- rust-libs/modules/gva/gql/src/mutations.rs | 86 - rust-libs/modules/gva/gql/src/pagination.rs | 73 - rust-libs/modules/gva/gql/src/queries.rs | 86 - .../gva/gql/src/queries/account_balance.rs | 143 -- .../modules/gva/gql/src/queries/block.rs | 142 -- .../gva/gql/src/queries/current_block.rs | 65 - .../gva/gql/src/queries/current_frame.rs | 94 - .../gql/src/queries/first_utxos_of_scripts.rs | 65 - .../modules/gva/gql/src/queries/gen_tx.rs | 277 --- rust-libs/modules/gva/gql/src/queries/idty.rs | 81 - .../modules/gva/gql/src/queries/network.rs | 144 -- .../gva/gql/src/queries/txs_history.rs | 345 ---- rust-libs/modules/gva/gql/src/queries/uds.rs | 185 -- .../gva/gql/src/queries/utxos_of_script.rs | 103 - rust-libs/modules/gva/gql/src/scalars.rs | 83 - rust-libs/modules/gva/gql/src/schema.rs | 74 - .../modules/gva/gql/src/subscriptions.rs | 62 - .../gva/gql/src/subscriptions/new_blocks.rs | 51 - .../src/subscriptions/receive_pending_txs.rs | 52 - rust-libs/modules/gva/indexer/Cargo.toml | 25 - .../modules/gva/indexer/src/identities.rs | 80 - rust-libs/modules/gva/indexer/src/lib.rs | 593 ------ rust-libs/modules/gva/indexer/src/tx.rs | 514 ----- rust-libs/modules/gva/indexer/src/utxos.rs | 86 - rust-libs/modules/gva/src/anti_spam.rs | 201 -- rust-libs/modules/gva/src/lib.rs | 367 ---- rust-libs/modules/gva/src/warp_.rs | 323 --- .../duniter-integration-tests/Cargo.toml | 7 +- rust-libs/tools/kv_typed/Cargo.toml | 59 - .../kv_typed/benches/compare_backends.rs | 146 -- rust-libs/tools/kv_typed/src/as_bytes.rs | 86 - rust-libs/tools/kv_typed/src/backend.rs | 100 - .../tools/kv_typed/src/backend/leveldb.rs | 364 ---- rust-libs/tools/kv_typed/src/backend/lmdb.rs | 404 ---- .../tools/kv_typed/src/backend/memory.rs | 284 --- .../kv_typed/src/backend/memory_singleton.rs | 186 -- rust-libs/tools/kv_typed/src/backend/mock.rs | 85 - rust-libs/tools/kv_typed/src/backend/sled.rs | 205 -- rust-libs/tools/kv_typed/src/batch.rs | 106 - rust-libs/tools/kv_typed/src/bytes.rs | 62 - .../tools/kv_typed/src/collection_inner.rs | 43 - rust-libs/tools/kv_typed/src/collection_ro.rs | 267 --- rust-libs/tools/kv_typed/src/collection_rw.rs | 100 - rust-libs/tools/kv_typed/src/db_schema.rs | 242 --- rust-libs/tools/kv_typed/src/error.rs | 75 - rust-libs/tools/kv_typed/src/event.rs | 31 - rust-libs/tools/kv_typed/src/explorer.rs | 529 ----- rust-libs/tools/kv_typed/src/from_bytes.rs | 127 -- rust-libs/tools/kv_typed/src/iter.rs | 214 -- rust-libs/tools/kv_typed/src/iter/keys.rs | 53 - rust-libs/tools/kv_typed/src/iter/values.rs | 59 - rust-libs/tools/kv_typed/src/key.rs | 93 - rust-libs/tools/kv_typed/src/lib.rs | 153 -- rust-libs/tools/kv_typed/src/subscription.rs | 102 - .../tools/kv_typed/src/transactional_read.rs | 211 -- .../tools/kv_typed/src/transactional_write.rs | 237 --- .../src/transactional_write/tx_iter.rs | 157 -- rust-libs/tools/kv_typed/src/utils.rs | 24 - rust-libs/tools/kv_typed/src/utils/arc.rs | 267 --- rust-libs/tools/kv_typed/src/utils/ivec.rs | 314 --- rust-libs/tools/kv_typed/src/value.rs | 155 -- .../tools/kv_typed/tests/test_db_schema.rs | 221 -- rust-libs/tools/kv_typed/tests/test_mock.rs | 54 - 205 files changed, 463 insertions(+), 26831 deletions(-) delete mode 100644 rust-libs/dubp-wot/Cargo.toml delete mode 100644 rust-libs/dubp-wot/README.md delete mode 100644 rust-libs/dubp-wot/src/data/mod.rs delete mode 100644 rust-libs/dubp-wot/src/data/rusty.rs delete mode 100644 rust-libs/dubp-wot/src/lib.rs delete mode 100644 rust-libs/dubp-wot/src/operations/centrality.rs delete mode 100644 rust-libs/dubp-wot/src/operations/density.rs delete mode 100644 rust-libs/dubp-wot/src/operations/distance.rs delete mode 100644 rust-libs/dubp-wot/src/operations/mod.rs delete mode 100644 rust-libs/dubp-wot/src/operations/path.rs delete mode 100644 rust-libs/dubp-wot/tests/g1_genesis.bin delete mode 100644 rust-libs/dubp-wot/tests/g1_genesis.bin.gz delete mode 100644 rust-libs/duniter-bc-reader/Cargo.toml delete mode 100644 rust-libs/duniter-bc-reader/src/lib.rs delete mode 100644 rust-libs/duniter-conf/Cargo.toml delete mode 100644 rust-libs/duniter-conf/src/gva_conf.rs delete mode 100644 rust-libs/duniter-conf/src/lib.rs delete mode 100644 rust-libs/duniter-dbs-write-ops/Cargo.toml delete mode 100644 rust-libs/duniter-dbs-write-ops/src/apply_block.rs delete mode 100644 rust-libs/duniter-dbs-write-ops/src/bc.rs delete mode 100644 rust-libs/duniter-dbs-write-ops/src/bc/identities.rs delete mode 100644 rust-libs/duniter-dbs-write-ops/src/bc/txs.rs delete mode 100644 rust-libs/duniter-dbs-write-ops/src/bc/uds.rs delete mode 100644 rust-libs/duniter-dbs-write-ops/src/cm.rs delete mode 100644 rust-libs/duniter-dbs-write-ops/src/lib.rs delete mode 100644 rust-libs/duniter-dbs-write-ops/src/txs_mp.rs delete mode 100644 rust-libs/duniter-dbs/Cargo.toml delete mode 100644 rust-libs/duniter-dbs/src/databases.rs delete mode 100644 rust-libs/duniter-dbs/src/databases/bc_v1.rs delete mode 100644 rust-libs/duniter-dbs/src/databases/bc_v2.rs delete mode 100644 rust-libs/duniter-dbs/src/databases/cm_v1.rs delete mode 100644 rust-libs/duniter-dbs/src/databases/network_v1.rs delete mode 100644 rust-libs/duniter-dbs/src/databases/txs_mp_v2.rs delete mode 100644 rust-libs/duniter-dbs/src/keys.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/all.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/block_number.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/blockstamp.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/dunp_node_id.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/hash.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/pubkey.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/pubkey_and_sig.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/source_key.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/timestamp.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/ud_id.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/uid.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/utxo_id.rs delete mode 100644 rust-libs/duniter-dbs/src/keys/wallet_conditions.rs delete mode 100644 rust-libs/duniter-dbs/src/lib.rs delete mode 100644 rust-libs/duniter-dbs/src/open_dbs.rs delete mode 100644 rust-libs/duniter-dbs/src/values.rs delete mode 100644 rust-libs/duniter-dbs/src/values/block_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/block_head_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/block_meta.rs delete mode 100644 rust-libs/duniter-dbs/src/values/block_number_array_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/cindex_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/dunp_head.rs delete mode 100644 rust-libs/duniter-dbs/src/values/idty_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/iindex_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/kick_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/mindex_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/peer_card.rs delete mode 100644 rust-libs/duniter-dbs/src/values/pubkey_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/sindex_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/source_amount.rs delete mode 100644 rust-libs/duniter-dbs/src/values/tx_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/txs.rs delete mode 100644 rust-libs/duniter-dbs/src/values/ud_entry_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/utxo.rs delete mode 100644 rust-libs/duniter-dbs/src/values/wallet_db.rs delete mode 100644 rust-libs/duniter-dbs/src/values/wallet_script_with_sa.rs delete mode 100644 rust-libs/duniter-dbs/tests/test_explorer.rs delete mode 100644 rust-libs/duniter-dbs/tests/test_read_write.rs delete mode 100644 rust-libs/duniter-dbs/tests/test_tmp_real.rs delete mode 100644 rust-libs/duniter-global/Cargo.toml delete mode 100644 rust-libs/duniter-global/src/lib.rs delete mode 100644 rust-libs/duniter-mempools/Cargo.toml delete mode 100644 rust-libs/duniter-mempools/src/lib.rs delete mode 100644 rust-libs/duniter-module/Cargo.toml delete mode 100644 rust-libs/duniter-module/src/lib.rs delete mode 100644 rust-libs/modules/gva/Cargo.toml delete mode 100644 rust-libs/modules/gva/bca/Cargo.toml delete mode 100644 rust-libs/modules/gva/bca/src/exec_req_type.rs delete mode 100644 rust-libs/modules/gva/bca/src/exec_req_type/balances.rs delete mode 100644 rust-libs/modules/gva/bca/src/exec_req_type/current_ud.rs delete mode 100644 rust-libs/modules/gva/bca/src/exec_req_type/last_blockstamp_out_of_fork_window.rs delete mode 100644 rust-libs/modules/gva/bca/src/exec_req_type/members_count.rs delete mode 100644 rust-libs/modules/gva/bca/src/exec_req_type/prepare_simple_payment.rs delete mode 100644 rust-libs/modules/gva/bca/src/exec_req_type/send_txs.rs delete mode 100644 rust-libs/modules/gva/bca/src/exec_req_type/utxos.rs delete mode 100644 rust-libs/modules/gva/bca/src/lib.rs delete mode 100644 rust-libs/modules/gva/bca/types/Cargo.toml delete mode 100644 rust-libs/modules/gva/bca/types/src/amount.rs delete mode 100644 rust-libs/modules/gva/bca/types/src/identity.rs delete mode 100644 rust-libs/modules/gva/bca/types/src/lib.rs delete mode 100644 rust-libs/modules/gva/bca/types/src/prepare_payment.rs delete mode 100644 rust-libs/modules/gva/bca/types/src/rejected_tx.rs delete mode 100644 rust-libs/modules/gva/bca/types/src/utxo.rs delete mode 100644 rust-libs/modules/gva/db/Cargo.toml delete mode 100644 rust-libs/modules/gva/db/src/keys.rs delete mode 100644 rust-libs/modules/gva/db/src/keys/gva_utxo_id.rs delete mode 100644 rust-libs/modules/gva/db/src/keys/wallet_hash_with_bn.rs delete mode 100644 rust-libs/modules/gva/db/src/lib.rs delete mode 100644 rust-libs/modules/gva/db/src/values.rs delete mode 100644 rust-libs/modules/gva/db/src/values/gva_idty_db.rs delete mode 100644 rust-libs/modules/gva/db/src/values/gva_tx.rs delete mode 100644 rust-libs/modules/gva/db/src/values/wallet_script_array.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/Cargo.toml delete mode 100644 rust-libs/modules/gva/dbs-reader/src/block.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/src/current_frame.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/src/find_inputs.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/src/idty.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/src/lib.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/src/network.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/src/pagination.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/src/txs_history.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/src/uds_of_pubkey.rs delete mode 100644 rust-libs/modules/gva/dbs-reader/src/utxos.rs delete mode 100644 rust-libs/modules/gva/gql/Cargo.toml delete mode 100644 rust-libs/modules/gva/gql/src/entities.rs delete mode 100644 rust-libs/modules/gva/gql/src/entities/block_gva.rs delete mode 100644 rust-libs/modules/gva/gql/src/entities/idty_gva.rs delete mode 100644 rust-libs/modules/gva/gql/src/entities/network.rs delete mode 100644 rust-libs/modules/gva/gql/src/entities/tx_gva.rs delete mode 100644 rust-libs/modules/gva/gql/src/entities/ud_gva.rs delete mode 100644 rust-libs/modules/gva/gql/src/entities/utxos_gva.rs delete mode 100644 rust-libs/modules/gva/gql/src/inputs.rs delete mode 100644 rust-libs/modules/gva/gql/src/inputs_validators.rs delete mode 100644 rust-libs/modules/gva/gql/src/lib.rs delete mode 100644 rust-libs/modules/gva/gql/src/mutations.rs delete mode 100644 rust-libs/modules/gva/gql/src/pagination.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/account_balance.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/block.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/current_block.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/current_frame.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/first_utxos_of_scripts.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/gen_tx.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/idty.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/network.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/txs_history.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/uds.rs delete mode 100644 rust-libs/modules/gva/gql/src/queries/utxos_of_script.rs delete mode 100644 rust-libs/modules/gva/gql/src/scalars.rs delete mode 100644 rust-libs/modules/gva/gql/src/schema.rs delete mode 100644 rust-libs/modules/gva/gql/src/subscriptions.rs delete mode 100644 rust-libs/modules/gva/gql/src/subscriptions/new_blocks.rs delete mode 100644 rust-libs/modules/gva/gql/src/subscriptions/receive_pending_txs.rs delete mode 100644 rust-libs/modules/gva/indexer/Cargo.toml delete mode 100644 rust-libs/modules/gva/indexer/src/identities.rs delete mode 100644 rust-libs/modules/gva/indexer/src/lib.rs delete mode 100644 rust-libs/modules/gva/indexer/src/tx.rs delete mode 100644 rust-libs/modules/gva/indexer/src/utxos.rs delete mode 100644 rust-libs/modules/gva/src/anti_spam.rs delete mode 100644 rust-libs/modules/gva/src/lib.rs delete mode 100644 rust-libs/modules/gva/src/warp_.rs delete mode 100644 rust-libs/tools/kv_typed/Cargo.toml delete mode 100644 rust-libs/tools/kv_typed/benches/compare_backends.rs delete mode 100644 rust-libs/tools/kv_typed/src/as_bytes.rs delete mode 100644 rust-libs/tools/kv_typed/src/backend.rs delete mode 100644 rust-libs/tools/kv_typed/src/backend/leveldb.rs delete mode 100644 rust-libs/tools/kv_typed/src/backend/lmdb.rs delete mode 100644 rust-libs/tools/kv_typed/src/backend/memory.rs delete mode 100644 rust-libs/tools/kv_typed/src/backend/memory_singleton.rs delete mode 100644 rust-libs/tools/kv_typed/src/backend/mock.rs delete mode 100644 rust-libs/tools/kv_typed/src/backend/sled.rs delete mode 100644 rust-libs/tools/kv_typed/src/batch.rs delete mode 100644 rust-libs/tools/kv_typed/src/bytes.rs delete mode 100644 rust-libs/tools/kv_typed/src/collection_inner.rs delete mode 100644 rust-libs/tools/kv_typed/src/collection_ro.rs delete mode 100644 rust-libs/tools/kv_typed/src/collection_rw.rs delete mode 100644 rust-libs/tools/kv_typed/src/db_schema.rs delete mode 100644 rust-libs/tools/kv_typed/src/error.rs delete mode 100644 rust-libs/tools/kv_typed/src/event.rs delete mode 100644 rust-libs/tools/kv_typed/src/explorer.rs delete mode 100644 rust-libs/tools/kv_typed/src/from_bytes.rs delete mode 100644 rust-libs/tools/kv_typed/src/iter.rs delete mode 100644 rust-libs/tools/kv_typed/src/iter/keys.rs delete mode 100644 rust-libs/tools/kv_typed/src/iter/values.rs delete mode 100644 rust-libs/tools/kv_typed/src/key.rs delete mode 100644 rust-libs/tools/kv_typed/src/lib.rs delete mode 100644 rust-libs/tools/kv_typed/src/subscription.rs delete mode 100644 rust-libs/tools/kv_typed/src/transactional_read.rs delete mode 100644 rust-libs/tools/kv_typed/src/transactional_write.rs delete mode 100644 rust-libs/tools/kv_typed/src/transactional_write/tx_iter.rs delete mode 100644 rust-libs/tools/kv_typed/src/utils.rs delete mode 100644 rust-libs/tools/kv_typed/src/utils/arc.rs delete mode 100644 rust-libs/tools/kv_typed/src/utils/ivec.rs delete mode 100644 rust-libs/tools/kv_typed/src/value.rs delete mode 100644 rust-libs/tools/kv_typed/tests/test_db_schema.rs delete mode 100644 rust-libs/tools/kv_typed/tests/test_mock.rs diff --git a/Cargo.lock b/Cargo.lock index 7dd78769f..8e4c7d79f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,61 +12,24 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.13.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" dependencies = [ "gimli", ] [[package]] name = "adler" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" - -[[package]] -name = "aes" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" -dependencies = [ - "aes-soft", - "aesni", - "cipher", -] - -[[package]] -name = "aes-soft" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" -dependencies = [ - "cipher", - "opaque-debug 0.3.0", -] - -[[package]] -name = "aesni" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" -dependencies = [ - "cipher", - "opaque-debug 0.3.0", -] - -[[package]] -name = "ahash" -version = "0.3.8" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] @@ -80,26 +43,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anyhow" -version = "1.0.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7" - -[[package]] -name = "arc-swap" -version = "0.4.7" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" +checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" [[package]] name = "arrayref" @@ -116,16 +64,6 @@ dependencies = [ "serde", ] -[[package]] -name = "async-attributes" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd3d156917d94862e779f356c5acae312b08fd3121e792c857d7928c8088423" -dependencies = [ - "quote", - "syn", -] - [[package]] name = "async-bincode" version = "0.6.1" @@ -141,87 +79,38 @@ dependencies = [ "tokio", ] -[[package]] -name = "async-channel" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d373d78ded7d0b3fa8039375718cde0aace493f2e34fb60f51cbf567562ca801" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "vec-arena", -] - -[[package]] -name = "async-global-executor" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "124ac8c265e407641c3362b8f4d39cdb4e243885b71eef087be27199790f5a3a" -dependencies = [ - "async-executor", - "async-io", - "futures-lite", - "num_cpus", - "once_cell", -] - [[package]] name = "async-graphql" -version = "2.2.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c961bdf28cec79b4254c642cf8e55071ec6b7101b3a189ce17a61b909d70951" +checksum = "bb5e71af65ee4a367603829e92b26710caf4116d1eaca8953dedf1809b33694a" dependencies = [ "async-graphql-derive", "async-graphql-parser", "async-graphql-value", - "async-mutex", "async-stream", "async-trait", - "blocking", - "bson", - "chrono", - "chrono-tz", "fnv", "futures-util", + "http", "indexmap", "log", - "lru", "multer", - "num-traits", "once_cell", - "pin-project-lite 0.2.0", + "pin-project-lite", "regex", "serde", "serde_json", - "sha2", - "spin 0.7.0", "static_assertions", "tempfile", "thiserror", - "tracing", - "url", - "uuid", ] [[package]] name = "async-graphql-derive" -version = "2.2.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e8975da7722a0f338b3df87214299e5655bba607ce15eeb15d82daf2820333" +checksum = "6fd4c2eb837e894909fe13509f2351fa3990c114426e41255936800892ccbe26" dependencies = [ "Inflector", "async-graphql-parser", @@ -235,9 +124,9 @@ dependencies = [ [[package]] name = "async-graphql-parser" -version = "2.1.2" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee04e49c932b12a7a18163a59ee5596a83422e4b91cb64ca63e3545bd4c4560e" +checksum = "2a8d8116f3015b7686ef98ffb70a74183c3c17bf45135993d3f095812e09e786" dependencies = [ "async-graphql-value", "pest", @@ -248,34 +137,14 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "2.0.5" +version = "2.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d3aa3cd3696ffd8decb10f5053affc78cb33ecfc545e480072bbc600e6723d" +checksum = "d8342ada84efe4b3d59e1313d1d2740a8ccfc76ddb57ccf55e45a6464dd7d0d3" dependencies = [ "serde", "serde_json", ] -[[package]] -name = "async-io" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54bc4c1c7292475efb2253227dbcfad8fe1ca4c02bc62c510cc2f3da5c4704e" -dependencies = [ - "concurrent-queue", - "fastrand", - "futures-lite", - "libc", - "log", - "nb-connect", - "once_cell", - "parking", - "polling", - "vec-arena", - "waker-fn", - "winapi", -] - [[package]] name = "async-mutex" version = "1.4.0" @@ -304,39 +173,11 @@ dependencies = [ "event-listener", ] -[[package]] -name = "async-std" -version = "1.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9fa76751505e8df1c7a77762f60486f60c71bbd9b8557f4da6ad47d083732ed" -dependencies = [ - "async-attributes", - "async-global-executor", - "async-io", - "async-mutex", - "blocking", - "crossbeam-utils 0.7.2", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "num_cpus", - "once_cell", - "pin-project-lite 0.1.11", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - [[package]] name = "async-stream" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3670df70cbc01729f901f94c887814b3c68db038aad1329a418bae178bc5295c" +checksum = "0a26cb53174ddd320edfff199a853f93d571f48eeb4dde75e67a9a3dbb7b7e5e" dependencies = [ "async-stream-impl", "futures-core", @@ -344,26 +185,20 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3548b8efc9f8e8a5a0a2808c5bd8451a9031b9e5b879a79590304ae928b0a70" +checksum = "db134ba52475c060f3329a8ef0f8786d6b872ed01515d4b79c162e5798da1340" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "async-task" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" - [[package]] name = "async-trait" -version = "0.1.41" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0" +checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" dependencies = [ "proc-macro2", "quote", @@ -381,12 +216,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - [[package]] name = "atty" version = "0.2.14" @@ -398,12 +227,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" - [[package]] name = "autocfg" version = "1.0.1" @@ -412,9 +235,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.53" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707b586e0e2f247cbde68cdd2c3ce69ea7b7be43e1c5b426e37c9319c4b9838e" +checksum = "78ed203b9ba68b242c62b3fb7480f589dd49829be1edb3fe8fc8b4ffda2dcb8d" dependencies = [ "addr2line", "cfg-if 1.0.0", @@ -424,12 +247,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - [[package]] name = "base64" version = "0.13.0" @@ -444,20 +261,13 @@ checksum = "6736e2428df2ca2848d846c43e88745121a6654696e349ce0054a420815a7409" [[package]] name = "bincode" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d175dfa69e619905c4c3cdb7c3c203fa3bdd5d51184e3afdb2742c0280493772" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ - "byteorder", "serde", ] -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" - [[package]] name = "bitflags" version = "1.2.1" @@ -466,9 +276,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake2b_simd" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" dependencies = [ "arrayref", "arrayvec", @@ -499,7 +309,7 @@ dependencies = [ "block-padding", "byte-tools", "byteorder", - "generic-array 0.12.3", + "generic-array 0.12.4", ] [[package]] @@ -520,20 +330,6 @@ dependencies = [ "byte-tools", ] -[[package]] -name = "blocking" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" -dependencies = [ - "async-channel", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "once_cell", -] - [[package]] name = "bs58" version = "0.3.1" @@ -546,34 +342,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" -[[package]] -name = "bson" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11f16001d679cb13d14b2c93c7d0fa13bb484a87c34a6c4c39707ad936499b5" -dependencies = [ - "base64 0.12.3", - "chrono", - "hex", - "lazy_static", - "linked-hash-map", - "rand 0.7.3", - "serde", - "serde_json", -] - -[[package]] -name = "bstr" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - [[package]] name = "buf_redux" version = "0.8.4" @@ -586,9 +354,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.4.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" +checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" [[package]] name = "byte-tools" @@ -598,9 +366,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" @@ -614,21 +382,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" -[[package]] -name = "cache-padded" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" - -[[package]] -name = "cast" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" -dependencies = [ - "rustc_version 0.2.3", -] - [[package]] name = "cc" version = "1.0.67" @@ -663,16 +416,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "chrono-tz" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120" -dependencies = [ - "chrono", - "parse-zoneinfo", -] - [[package]] name = "ci_info" version = "0.10.2" @@ -682,53 +425,26 @@ dependencies = [ "envmnt", ] -[[package]] -name = "cipher" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" -dependencies = [ - "generic-array 0.14.4", -] - [[package]] name = "clap" version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ - "ansi_term 0.11.0", + "ansi_term", "atty", - "bitflags 1.2.1", + "bitflags", "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags 1.2.1", -] - -[[package]] -name = "cloudabi" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" -dependencies = [ - "bitflags 1.2.1", -] - [[package]] name = "cmake" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e56268c17a6248366d66d4a47a3381369d068cce8409bb1716ed77ea32163bb" +checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855" dependencies = [ "cc", ] @@ -744,27 +460,18 @@ dependencies = [ "strum_macros", ] -[[package]] -name = "concurrent-queue" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" -dependencies = [ - "cache-padded", -] - -[[package]] -name = "const_fn" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2" - [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cpuid-bool" version = "0.1.2" @@ -780,50 +487,14 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "criterion" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8" -dependencies = [ - "atty", - "cast", - "clap", - "criterion-plot", - "csv", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_cbor", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" -dependencies = [ - "cast", - "itertools", -] - [[package]] name = "crossbeam-channel" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.0", + "crossbeam-utils", ] [[package]] @@ -834,18 +505,17 @@ checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils 0.8.0", + "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" +checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" dependencies = [ "cfg-if 1.0.0", - "const_fn", - "crossbeam-utils 0.8.0", + "crossbeam-utils", "lazy_static", "memoffset", "scopeguard", @@ -853,24 +523,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg 1.0.1", - "cfg-if 0.1.10", - "lazy_static", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ - "autocfg 1.0.1", + "autocfg", "cfg-if 1.0.0", - "const_fn", "lazy_static", ] @@ -880,7 +538,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c" dependencies = [ - "bitflags 1.2.1", + "bitflags", "crossterm_winapi", "lazy_static", "libc", @@ -921,45 +579,13 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "697c714f50560202b1f4e2e09cd50a421881c83e9025db75d15f276616f04f40" -[[package]] -name = "csv" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" -dependencies = [ - "bstr", - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "ctor" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" -dependencies = [ - "quote", - "syn", -] - [[package]] name = "ctrlc" -version = "3.1.7" +version = "3.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b57a92e9749e10f25a171adcebfafe72991d45e7ec2dcb853e8f83d9dafaeb08" +checksum = "232295399409a8b7ae41276757b5a1cc21032848d42bff2352261f958b3ca29a" dependencies = [ - "nix 0.18.0", + "nix 0.20.0", "winapi", ] @@ -976,9 +602,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.10.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" dependencies = [ "darling_core", "darling_macro", @@ -986,23 +612,23 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.10.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.9.3", + "strsim 0.10.0", "syn", ] [[package]] name = "darling_macro" -version = "0.10.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" dependencies = [ "darling_core", "quote", @@ -1011,34 +637,23 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.11" +version = "0.99.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" +checksum = "f82b1b72f1263f214c0f823371768776c4f5841b942c9883aa8e5ec584fd0ba6" dependencies = [ + "convert_case", "proc-macro2", "quote", "syn", ] -[[package]] -name = "diff" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" - -[[package]] -name = "difference" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" - [[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array 0.12.3", + "generic-array 0.12.4", ] [[package]] @@ -1076,17 +691,11 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" -[[package]] -name = "downcast" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb454f0228b18c7f4c3b0ebbee346ed9c52e7443b0999cd543ff3571205701d" - [[package]] name = "dubp" -version = "0.51.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21dac0f098a82c2782208a2bbd64caf27daafbf439d783e8a2b6589efc9e3dae" +checksum = "914faa8052c72c8b2f513a44398123379d70a59dfedf0aa8dc7b581ee223fbfc" dependencies = [ "dubp-block", "dubp-common", @@ -1098,9 +707,9 @@ dependencies = [ [[package]] name = "dubp-block" -version = "0.51.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7db42ae9c39478b09d08b56fe7c5acfc31317a46fe3c3ba9df3438154c1410" +checksum = "b15cc90473a86c4987ea34211829d491dfb56f7c09ba79ac3d57d9430782d038" dependencies = [ "dubp-documents", "dubp-documents-parser", @@ -1113,9 +722,9 @@ dependencies = [ [[package]] name = "dubp-common" -version = "0.51.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328a6ae4c29ae95253a18314cd2d7f5e04bf48a8de40a473172734e485370fd9" +checksum = "b3a5a6cc11940e0a85f492325fec45c557c5f103c92ea445427b4272c1a12395" dependencies = [ "dup-crypto", "serde", @@ -1126,9 +735,9 @@ dependencies = [ [[package]] name = "dubp-documents" -version = "0.51.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c501db59e9334ac22022baae5f51bb6e73d53a38b9f015015c770f83437da4" +checksum = "85d43233426a5a24a5d22e98da2d8f0efab9739a58af15fa27e74a213b2d5bb9" dependencies = [ "beef", "dubp-wallet", @@ -1140,9 +749,9 @@ dependencies = [ [[package]] name = "dubp-documents-parser" -version = "0.51.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12c38b138c7f5b6fbc219062548e04fce72dbf263400e50b106f39dec2b94f1d" +checksum = "ac382364d99af3c235530f9de41a1833d18a16dff8833a7b351e8946d378de18" dependencies = [ "dubp-documents", "json-pest-parser", @@ -1154,9 +763,9 @@ dependencies = [ [[package]] name = "dubp-wallet" -version = "0.51.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc7edb25227bbcfda2026a208022cc2ab8c43be0b7923f8281d572d253085a6" +checksum = "47cc059e6b139def809f9d0bf776a21f5c2d59fefc20ed30c7aceedfef8de703" dependencies = [ "byteorder", "dubp-common", @@ -1169,8 +778,8 @@ dependencies = [ [[package]] name = "dubp-wot" version = "0.11.0" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" dependencies = [ - "bincode", "log", "rayon", "serde", @@ -1179,17 +788,18 @@ dependencies = [ [[package]] name = "duniter-bc-reader" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" dependencies = [ "anyhow", "dubp", "duniter-dbs", "resiter", - "smallvec", ] [[package]] name = "duniter-bca" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/modules/duniter-gva#7c1f8e58872fe2931f780c9b5e6b80caa3f3683a" dependencies = [ "anyhow", "arrayvec", @@ -1198,14 +808,11 @@ dependencies = [ "bincode", "dubp", "duniter-bca-types", - "duniter-dbs", - "duniter-global", + "duniter-core", "duniter-gva-db", "duniter-gva-dbs-reader", - "duniter-mempools", "fast-threadpool", "futures", - "mockall", "once_cell", "smallvec", "tokio", @@ -1215,6 +822,7 @@ dependencies = [ [[package]] name = "duniter-bca-types" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/modules/duniter-gva#7c1f8e58872fe2931f780c9b5e6b80caa3f3683a" dependencies = [ "arrayvec", "bincode", @@ -1227,11 +835,26 @@ dependencies = [ [[package]] name = "duniter-conf" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" dependencies = [ "dubp", "serde", ] +[[package]] +name = "duniter-core" +version = "1.8.1" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" +dependencies = [ + "duniter-bc-reader", + "duniter-conf", + "duniter-dbs", + "duniter-dbs-write-ops", + "duniter-global", + "duniter-mempools", + "duniter-module", +] + [[package]] name = "duniter-dbex" version = "0.1.0" @@ -1241,8 +864,7 @@ dependencies = [ "comfy-table", "dirs", "dubp", - "duniter-dbs", - "duniter-dbs-write-ops", + "duniter-core", "duniter-gva-db", "duniter-gva-indexer", "fast-threadpool", @@ -1259,8 +881,8 @@ dependencies = [ [[package]] name = "duniter-dbs" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" dependencies = [ - "anyhow", "arrayvec", "bincode", "byteorder", @@ -1268,25 +890,22 @@ dependencies = [ "dubp", "kv_typed", "log", - "mockall", "parking_lot", "paste", "rand 0.7.3", "serde", "serde_json", "smallvec", - "tempfile", "thiserror", "uninit", - "unwrap", "zerocopy", ] [[package]] name = "duniter-dbs-write-ops" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" dependencies = [ - "anyhow", "chrono", "dubp", "duniter-dbs", @@ -1294,20 +913,18 @@ dependencies = [ "fast-threadpool", "flume", "log", - "maplit", "resiter", - "serde_json", ] [[package]] name = "duniter-global" version = "1.8.1" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" dependencies = [ "async-rwlock", "dubp", "duniter-dbs", "flume", - "mockall", "once_cell", "tokio", ] @@ -1315,6 +932,7 @@ dependencies = [ [[package]] name = "duniter-gva" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/modules/duniter-gva#7c1f8e58872fe2931f780c9b5e6b80caa3f3683a" dependencies = [ "anyhow", "arrayvec", @@ -1324,39 +942,32 @@ dependencies = [ "bytes 1.0.1", "dubp", "duniter-bca", - "duniter-conf", - "duniter-dbs", - "duniter-global", + "duniter-core", "duniter-gva-db", "duniter-gva-dbs-reader", "duniter-gva-gql", "duniter-gva-indexer", - "duniter-mempools", - "duniter-module", "fast-threadpool", "flume", "futures", "http", "log", - "mockall", "resiter", "serde", - "serde_json", "serde_urlencoded", "tokio", - "unwrap", "warp", ] [[package]] name = "duniter-gva-db" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/modules/duniter-gva#7c1f8e58872fe2931f780c9b5e6b80caa3f3683a" dependencies = [ "bincode", "chrono", "dubp", - "duniter-dbs", - "kv_typed", + "duniter-core", "parking_lot", "paste", "serde", @@ -1368,62 +979,49 @@ dependencies = [ [[package]] name = "duniter-gva-dbs-reader" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/modules/duniter-gva#7c1f8e58872fe2931f780c9b5e6b80caa3f3683a" dependencies = [ "anyhow", "arrayvec", "dubp", "duniter-bca-types", - "duniter-dbs", + "duniter-core", "duniter-gva-db", - "maplit", - "mockall", "resiter", - "smallvec", - "unwrap", ] [[package]] name = "duniter-gva-gql" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/modules/duniter-gva#7c1f8e58872fe2931f780c9b5e6b80caa3f3683a" dependencies = [ "anyhow", "arrayvec", "async-graphql", "async-trait", "dubp", - "duniter-bc-reader", - "duniter-conf", - "duniter-dbs", - "duniter-global", + "duniter-core", "duniter-gva-db", "duniter-gva-dbs-reader", - "duniter-mempools", - "duniter-module", "fast-threadpool", "flume", "futures", "log", - "mockall", - "pretty_assertions", "resiter", "serde", - "serde_json", - "tokio", - "unwrap", ] [[package]] name = "duniter-gva-indexer" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/modules/duniter-gva#7c1f8e58872fe2931f780c9b5e6b80caa3f3683a" dependencies = [ "anyhow", "dubp", - "duniter-dbs", + "duniter-core", "duniter-gva-db", - "maplit", "once_cell", "resiter", - "smallvec", ] [[package]] @@ -1432,12 +1030,7 @@ version = "0.1.0" dependencies = [ "anyhow", "dubp", - "duniter-bc-reader", - "duniter-conf", - "duniter-dbs", - "duniter-dbs-write-ops", - "duniter-mempools", - "duniter-module", + "duniter-core", "duniter-server", "fast-threadpool", "flume", @@ -1467,6 +1060,7 @@ dependencies = [ [[package]] name = "duniter-mempools" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" dependencies = [ "dubp", "duniter-bc-reader", @@ -1479,6 +1073,7 @@ dependencies = [ [[package]] name = "duniter-module" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" dependencies = [ "anyhow", "async-trait", @@ -1489,8 +1084,6 @@ dependencies = [ "duniter-mempools", "fast-threadpool", "log", - "paste", - "tokio", ] [[package]] @@ -1500,14 +1093,8 @@ dependencies = [ "anyhow", "cfg-if 1.0.0", "dubp", - "duniter-bc-reader", - "duniter-conf", - "duniter-dbs", - "duniter-dbs-write-ops", - "duniter-global", + "duniter-core", "duniter-gva", - "duniter-mempools", - "duniter-module", "fast-threadpool", "flume", "log", @@ -1537,20 +1124,16 @@ dependencies = [ [[package]] name = "dup-crypto" -version = "0.51.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "431ee425d40a19ac98b70b91b3afbbb3e5853397e95430694d07bb96a977a729" +checksum = "c3b8d3e1c65e3ed89db6973e807e9c355c8f9078866402e695a16683f1e226d2" dependencies = [ - "aes", - "arrayvec", - "base64 0.13.0", + "base64", "blake3", "bs58 0.4.0", "byteorder", "cryptoxide", - "ed25519-bip32", "getrandom 0.2.2", - "once_cell", "ring", "serde", "thiserror", @@ -1558,15 +1141,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ed25519-bip32" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8827180a2b511141fbe49141e50b31a8d542465e0fb572f81f36feea2addfe92" -dependencies = [ - "cryptoxide", -] - [[package]] name = "either" version = "1.6.1" @@ -1575,11 +1149,11 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" -version = "0.8.24" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2" +checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -1625,22 +1199,13 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "fastrand" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3" -dependencies = [ - "instant", -] - [[package]] name = "flate2" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee" +checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "crc32fast", "libc", "miniz_oxide", @@ -1659,24 +1224,16 @@ dependencies = [ "thiserror", ] -[[package]] -name = "float-cmp" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" -dependencies = [ - "num-traits", -] - [[package]] name = "flume" -version = "0.10.0" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e727ae0c455db3603e32c03fa722a8ccbd616b394eca686d76f9b2c9a91bb91" +checksum = "11fce69af4d4582ea989e6adfc5c9b81fd2071ff89234e5c14675c82a85217df" dependencies = [ "futures-core", "futures-sink", "nanorand", + "pin-project", "spinning_top", ] @@ -1688,20 +1245,14 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" dependencies = [ "matches", "percent-encoding", ] -[[package]] -name = "fragile" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a039c3498dc930fe810151a34ba0c1c70b02b8625035592e74432f678591f2" - [[package]] name = "fs2" version = "0.4.3" @@ -1722,17 +1273,11 @@ dependencies = [ "users", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "futures" -version = "0.3.7" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95314d38584ffbfda215621d723e0a3906f032e03ae5551e650058dac83d4797" +checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253" dependencies = [ "futures-channel", "futures-core", @@ -1745,9 +1290,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.8" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64" +checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25" dependencies = [ "futures-core", "futures-sink", @@ -1755,15 +1300,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.8" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" +checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815" [[package]] name = "futures-executor" -version = "0.3.7" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f8e0c9258abaea85e78ebdda17ef9666d390e987f006be6080dfe354b708cb" +checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d" dependencies = [ "futures-core", "futures-task", @@ -1772,30 +1317,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb" - -[[package]] -name = "futures-lite" -version = "1.11.2" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6c079abfac3ab269e2927ec048dabc89d009ebfdda6b8ee86624f30c689658" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite 0.1.11", - "waker-fn", -] +checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04" [[package]] name = "futures-macro" -version = "0.3.8" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556" +checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b" dependencies = [ "proc-macro-hack", "proc-macro2", @@ -1811,24 +1341,21 @@ checksum = "61e9325be55c5581082cd110294fa988c1f920bc573ec370ef201e33c469a95a" [[package]] name = "futures-sink" -version = "0.3.8" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d" +checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23" [[package]] name = "futures-task" -version = "0.3.8" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d" -dependencies = [ - "once_cell", -] +checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc" [[package]] name = "futures-util" -version = "0.3.8" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2" +checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025" dependencies = [ "futures-channel", "futures-core", @@ -1837,7 +1364,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project 1.0.1", + "pin-project-lite", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1853,17 +1380,11 @@ dependencies = [ "byteorder", ] -[[package]] -name = "gcc" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" - [[package]] name = "generic-array" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ "typenum", ] @@ -1889,11 +1410,11 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -1913,9 +1434,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" [[package]] name = "glob" @@ -1923,24 +1444,11 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" -[[package]] -name = "gloo-timers" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "h2" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b67e66362108efccd8ac053abafc8b7a8d86a37e6e48fc4f6f7485eb5e9e6a5" +checksum = "fc018e188373e2777d0ef2467ebff62a08e66c3f5857b23c8fbec3018210dc00" dependencies = [ "bytes 1.0.1", "fnv", @@ -1953,23 +1461,6 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "tracing-futures", -] - -[[package]] -name = "half" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" - -[[package]] -name = "hashbrown" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" -dependencies = [ - "ahash", - "autocfg 1.0.1", ] [[package]] @@ -1980,17 +1471,17 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" [[package]] name = "headers" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed18eb2459bf1a09ad2d6b1547840c3e5e62882fa09b9a6a20b1de8e3228848f" +checksum = "f0b7591fb62902706ae8e7aaff416b1b0fa2c0fd0878b46dc13baa3712d8a855" dependencies = [ - "base64 0.12.3", - "bitflags 1.2.1", - "bytes 0.5.6", + "base64", + "bitflags", + "bytes 1.0.1", "headers-core", "http", "mime", - "sha-1 0.8.2", + "sha-1 0.9.4", "time", ] @@ -2005,66 +1496,61 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" dependencies = [ "unicode-segmentation", ] [[package]] name = "hermit-abi" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] -[[package]] -name = "hex" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" - [[package]] name = "http" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" +checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" dependencies = [ - "bytes 0.5.6", + "bytes 1.0.1", "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994" +checksum = "5dfb77c123b4e2f72a2069aeae0b4b4949cc7e966df277813fc16347e7549737" dependencies = [ "bytes 1.0.1", "http", + "pin-project-lite", ] [[package]] name = "httparse" -version = "1.3.4" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +checksum = "4a1ce40d6fc9764887c2fdc7305c3dcc429ba11ff981c1509416afd5697e4437" [[package]] name = "httpdate" -version = "0.3.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "hyper" -version = "0.14.4" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e946c2b1349055e0b72ae281b238baf1a3ea7307c7e9f9d64673bdd9c26ac7" +checksum = "1e5f105c494081baa3bf9e200b279e27ec1623895cd504c7dbef8d0b080fcf54" dependencies = [ "bytes 1.0.1", "futures-channel", @@ -2076,7 +1562,7 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project 1.0.1", + "pin-project", "socket2", "tokio", "tower-service", @@ -2092,9 +1578,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" dependencies = [ "matches", "unicode-bidi", @@ -2103,12 +1589,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" +checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" dependencies = [ - "autocfg 1.0.1", - "hashbrown 0.9.1", + "autocfg", + "hashbrown", ] [[package]] @@ -2122,9 +1608,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" dependencies = [ "cfg-if 1.0.0", ] @@ -2140,24 +1626,24 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "jobserver" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.45" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" +checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c" dependencies = [ "wasm-bindgen", ] @@ -2174,28 +1660,15 @@ dependencies = [ "unwrap", ] -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "kv_typed" version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#f9abadd0145d848ba4df2ab545639355c7f20386" dependencies = [ - "async-std", "byteorder", "cfg-if 0.1.10", - "criterion", "flume", "leveldb_minimal", - "lmdb-zero", - "maybe-async", - "mockall", "parking_lot", "paste", "rayon", @@ -2203,10 +1676,8 @@ dependencies = [ "serde_json", "sled", "smallvec", - "tempfile", "thiserror", "uninit", - "unwrap", "zerocopy", ] @@ -2239,54 +1710,26 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" - -[[package]] -name = "liblmdb-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feed38a3a580f60bf61aaa067b0ff4123395966839adeaf67258a9e50c4d2e49" -dependencies = [ - "gcc", - "libc", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" - -[[package]] -name = "lmdb-zero" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13416eee745b087c22934f35f1f24da22da41ba2a5ce197143d168ce055cc58d" -dependencies = [ - "bitflags 0.9.1", - "libc", - "liblmdb-sys", - "supercow", -] +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" [[package]] name = "lock_api" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" +checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176" dependencies = [ "scopeguard", ] [[package]] name = "log" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -2295,15 +1738,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d0925aed5b12ed59857f438d25a910cf051dbcd4107907be1e7abf6c44ec903" -[[package]] -name = "lru" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "111b945ac72ec09eb7bc62a0fbdc3cc6e80555a7245f52a69d3921a75b53b153" -dependencies = [ - "hashbrown 0.8.2", -] - [[package]] name = "maplit" version = "1.0.2" @@ -2316,30 +1750,19 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -[[package]] -name = "maybe-async" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd1afac51d14f8056cd544c83239b961c464e0a98c2ca65353195df93e636a20" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "memchr" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "memoffset" -version = "0.5.6" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d" dependencies = [ - "autocfg 1.0.1", + "autocfg", ] [[package]] @@ -2360,19 +1783,19 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", - "autocfg 1.0.1", + "autocfg", ] [[package]] name = "mio" -version = "0.7.8" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc250d6848c90d719ea2ce34546fb5df7af1d3fd189d10bf7bad80bfcebecd95" +checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956" dependencies = [ "libc", "log", @@ -2383,41 +1806,13 @@ dependencies = [ [[package]] name = "miow" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "socket2", "winapi", ] -[[package]] -name = "mockall" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d614ad23f9bb59119b8b5670a85c7ba92c5e9adf4385c81ea00c51c8be33d5" -dependencies = [ - "cfg-if 1.0.0", - "downcast", - "fragile", - "lazy_static", - "mockall_derive", - "predicates", - "predicates-tree", -] - -[[package]] -name = "mockall_derive" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd4234635bca06fc96c7368d038061e0aae1b00a764dc817e900dc974e3deea" -dependencies = [ - "cfg-if 1.0.0", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "multer" version = "1.2.2" @@ -2439,9 +1834,9 @@ dependencies = [ [[package]] name = "multipart" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8209c33c951f07387a8497841122fc6f712165e3f9bda3e6be4645b58188f676" +checksum = "d050aeedc89243f5347c3e237e3e13dc76fbe4ae3742a57b94dc14f69acf76d4" dependencies = [ "buf_redux", "httparse", @@ -2449,7 +1844,7 @@ dependencies = [ "mime", "mime_guess", "quick-error", - "rand 0.6.5", + "rand 0.7.3", "safemem", "tempfile", "twoway 0.1.8", @@ -2457,23 +1852,13 @@ dependencies = [ [[package]] name = "nanorand" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3173d7bb904c5a3a2f9167eb936916a39e97124846b8316223323aed9a34d1e7" +checksum = "ac1378b66f7c93a1c0f8464a19bf47df8795083842e5090f4b7305973d5a22d0" dependencies = [ "getrandom 0.2.2", ] -[[package]] -name = "nb-connect" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "neon" version = "0.4.0" @@ -2541,7 +1926,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" dependencies = [ - "bitflags 1.2.1", + "bitflags", "cc", "cfg-if 0.1.10", "libc", @@ -2550,22 +1935,16 @@ dependencies = [ [[package]] name = "nix" -version = "0.18.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" +checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" dependencies = [ - "bitflags 1.2.1", + "bitflags", "cc", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", ] -[[package]] -name = "normalize-line-endings" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" - [[package]] name = "ntapi" version = "0.3.6" @@ -2594,27 +1973,27 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-traits", ] [[package]] name = "num-integer" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-integer", "num-traits", ] @@ -2625,18 +2004,18 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ - "autocfg 1.0.1", + "autocfg", ] [[package]] @@ -2651,21 +2030,15 @@ dependencies = [ [[package]] name = "object" -version = "0.21.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693" +checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" [[package]] name = "once_cell" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" - -[[package]] -name = "oorandom" -version = "11.1.2" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" [[package]] name = "opaque-debug" @@ -2679,26 +2052,11 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "output_vt100" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" -dependencies = [ - "winapi", -] - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - [[package]] name = "parking_lot" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ "instant", "lock_api", @@ -2707,33 +2065,23 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ - "cfg-if 0.1.10", - "cloudabi 0.1.0", + "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.1.57", + "redox_syscall 0.2.6", "smallvec", "winapi", ] -[[package]] -name = "parse-zoneinfo" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" -dependencies = [ - "regex", -] - [[package]] name = "paste" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba7ae1a2180ed02ddfdb5ab70c70d596a26dd642e097bb6fe78b1bde8588ed97" +checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" [[package]] name = "percent-encoding" @@ -2786,140 +2134,49 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15" -dependencies = [ - "pin-project-internal 0.4.27", -] - -[[package]] -name = "pin-project" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee41d838744f60d959d7074e3afb6b35c7456d0f61cad38a24e35e6553f73841" -dependencies = [ - "pin-project-internal 1.0.1", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.27" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" +checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" dependencies = [ - "proc-macro2", - "quote", - "syn", + "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" - -[[package]] -name = "pin-project-lite" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "plotters" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb" -dependencies = [ - "js-sys", - "num-traits", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "polling" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "log", - "wepoll-sys", - "winapi", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" - -[[package]] -name = "predicates" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bfead12e90dccead362d62bb2c90a5f6fc4584963645bc7f71a735e0b0735a" +checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" dependencies = [ - "difference", - "float-cmp", - "normalize-line-endings", - "predicates-core", - "regex", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "predicates-core" -version = "1.0.0" +name = "pin-project-lite" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178" +checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" [[package]] -name = "predicates-tree" -version = "1.0.0" +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124" -dependencies = [ - "predicates-core", - "treeline", -] +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "pretty_assertions" -version = "0.7.1" +name = "ppv-lite86" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f297542c27a7df8d45de2b0e620308ab883ad232d06c14b76ac3e144bda50184" -dependencies = [ - "ansi_term 0.12.1", - "ctor", - "diff", - "output_vt100", -] +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "proc-macro-crate" -version = "0.1.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "41fdbd1df62156fbc5945f4762632564d7d038153091c3fcf1067f6aef7cff92" dependencies = [ + "thiserror", "toml", ] @@ -2955,15 +2212,15 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-nested" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ "unicode-xid", ] @@ -2976,39 +2233,20 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.7", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi", -] - [[package]] name = "rand" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom 0.1.15", + "getrandom 0.1.16", "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", @@ -3027,16 +2265,6 @@ dependencies = [ "rand_hc 0.3.0", ] -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.3.1", -] - [[package]] name = "rand_chacha" version = "0.2.2" @@ -3057,28 +2285,13 @@ dependencies = [ "rand_core 0.6.2", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.15", + "getrandom 0.1.16", ] [[package]] @@ -3090,15 +2303,6 @@ dependencies = [ "getrandom 0.2.2", ] -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "rand_hc" version = "0.2.0" @@ -3117,66 +2321,13 @@ dependencies = [ "rand_core 0.6.2", ] -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi 0.0.3", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "rayon" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" dependencies = [ - "autocfg 1.0.1", + "autocfg", "crossbeam-deque", "either", "rayon-core", @@ -3190,20 +2341,11 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils 0.8.0", + "crossbeam-utils", "lazy_static", "num_cpus", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "read_input" version = "0.8.4" @@ -3218,11 +2360,11 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041" dependencies = [ - "bitflags 1.2.1", + "bitflags", ] [[package]] @@ -3231,37 +2373,27 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ - "getrandom 0.1.15", + "getrandom 0.1.16", "redox_syscall 0.1.57", "rust-argon2", ] [[package]] name = "regex" -version = "1.4.1" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b" +checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", -] - -[[package]] -name = "regex-automata" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" -dependencies = [ - "byteorder", ] [[package]] name = "regex-syntax" -version = "0.6.20" +version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c" +checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" [[package]] name = "remove_dir_all" @@ -3287,7 +2419,7 @@ dependencies = [ "cc", "libc", "once_cell", - "spin 0.5.2", + "spin", "untrusted", "web-sys", "winapi", @@ -3295,23 +2427,23 @@ dependencies = [ [[package]] name = "run_script" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e8fc35067815a04a35fe2144361e1257b0f1041f0d413664f38e44d1a73cb4" +checksum = "70f5efb6762d8cafcab5b2a5545dad239d896989b15304e7d1a03cc6cf1aa626" dependencies = [ "fsio", ] [[package]] name = "rust-argon2" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" dependencies = [ - "base64 0.12.3", + "base64", "blake2b_simd", "constant_time_eq", - "crossbeam-utils 0.7.2", + "crossbeam-utils", ] [[package]] @@ -3362,15 +2494,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "scoped-tls" version = "1.0.0" @@ -3418,28 +2541,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.124" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" +checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" dependencies = [ "serde_derive", ] -[[package]] -name = "serde_cbor" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" -dependencies = [ - "half", - "serde", -] - [[package]] name = "serde_derive" -version = "1.0.124" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" +checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" dependencies = [ "proc-macro2", "quote", @@ -3448,11 +2561,10 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.59" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" dependencies = [ - "indexmap", "itoa", "ryu", "serde", @@ -3484,22 +2596,9 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 0.1.10", - "cpuid-bool", - "digest 0.9.0", - "opaque-debug 0.3.0", -] - -[[package]] -name = "sha2" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8" +checksum = "dfebf75d25bd900fd1e7d11501efab59bc846dbc76196839663e6637bba9f25f" dependencies = [ "block-buffer 0.9.0", "cfg-if 1.0.0", @@ -3510,9 +2609,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604508c1418b99dfe1925ca9224829bb2a8a9a04dda655cc01fcad46f4ab05ed" +checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729" dependencies = [ "libc", "mio", @@ -3521,19 +2620,18 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035" +checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" dependencies = [ - "arc-swap", "libc", ] [[package]] name = "slab" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" [[package]] name = "sled" @@ -3543,7 +2641,7 @@ checksum = "1d0132f3e393bcb7390c60bb45769498cf4550bcb7a21d7f95c02b69f6362cdc" dependencies = [ "crc32fast", "crossbeam-epoch", - "crossbeam-utils 0.8.0", + "crossbeam-utils", "fs2", "fxhash", "libc", @@ -3563,9 +2661,9 @@ dependencies = [ [[package]] name = "snafu" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c4e6046e4691afe918fd1b603fd6e515bcda5388a1092a9edbada307d159f09" +checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" dependencies = [ "doc-comment", "snafu-derive", @@ -3573,9 +2671,9 @@ dependencies = [ [[package]] name = "snafu-derive" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7073448732a89f2f3e6581989106067f403d378faeafb4a50812eb814170d3e5" +checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" dependencies = [ "proc-macro2", "quote", @@ -3584,11 +2682,10 @@ dependencies = [ [[package]] name = "socket2" -version = "0.3.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" dependencies = [ - "cfg-if 1.0.0", "libc", "winapi", ] @@ -3599,17 +2696,11 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "spin" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652ac3743312871a5fb703f0337e68ffa3cdc28c863efad0b8dc858fa10c991b" - [[package]] name = "spinning_top" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e529d73e80d64b5f2631f9035113347c578a1c9c7774b83a2b880788459ab36" +checksum = "8bd0ab6b8c375d2d963503b90d3770010d95bc3b5f98036f948dee24bf4e8879" dependencies = [ "lock_api", ] @@ -3628,15 +2719,15 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "strsim" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "structopt" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126d630294ec449fae0b16f964e35bf3c74f940da9dca17ee9b905f7b3112eb8" +checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c" dependencies = [ "clap", "lazy_static", @@ -3645,9 +2736,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e51c492f9e23a220534971ff5afc14037289de430e3c83f9daf6a1b6ae91e8" +checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" dependencies = [ "heck", "proc-macro-error", @@ -3680,17 +2771,11 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" -[[package]] -name = "supercow" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171758edb47aa306a78dfa4ab9aeb5167405bd4e3dc2b64e88f6a84bbe98bd63" - [[package]] name = "syn" -version = "1.0.62" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" +checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883" dependencies = [ "proc-macro2", "quote", @@ -3718,16 +2803,16 @@ dependencies = [ "cfg-if 1.0.0", "libc", "rand 0.8.3", - "redox_syscall 0.2.5", + "redox_syscall 0.2.6", "remove_dir_all", "winapi", ] [[package]] name = "terminal_size" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd2d183bd3fac5f5fe38ddbeb4dc9aec4a39a9d7d59e7491d900302da01cbe1" +checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406" dependencies = [ "libc", "winapi", @@ -3772,15 +2857,6 @@ dependencies = [ "syn", ] -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - [[package]] name = "time" version = "0.1.44" @@ -3793,34 +2869,33 @@ dependencies = [ ] [[package]] -name = "tinytemplate" -version = "1.1.0" +name = "tinyvec" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d3dc76004a03cec1c5932bca4cdc2e39aaa798e3f82363dd94f9adf6098c12f" +checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" dependencies = [ - "serde", - "serde_json", + "tinyvec_macros", ] [[package]] -name = "tinyvec" -version = "0.3.4" +name = "tinyvec_macros" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.2.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a" +checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5" dependencies = [ - "autocfg 1.0.1", + "autocfg", "bytes 1.0.1", "libc", "memchr", "mio", "num_cpus", - "pin-project-lite 0.2.0", + "pin-project-lite", "tokio-macros", ] @@ -3837,12 +2912,12 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1981ad97df782ab506a1f43bf82c967326960d278acf3bf8279809648c3ff3ea" +checksum = "e177a5d8c3bf36de9ebe6d58537d8879e964332f93fb3339e43f618c81361af0" dependencies = [ "futures-core", - "pin-project-lite 0.2.0", + "pin-project-lite", "tokio", ] @@ -3854,64 +2929,52 @@ checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b" dependencies = [ "futures-util", "log", - "pin-project 1.0.1", + "pin-project", "tokio", "tungstenite", ] [[package]] name = "tokio-util" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebb7cb2f00c5ae8df755b252306272cd1790d39728363936e01827e11f0b017b" +checksum = "940a12c99365c31ea8dd9ba04ec1be183ffe4920102bb7122c2f515437601e8e" dependencies = [ "bytes 1.0.1", "futures-core", "futures-sink", "log", - "pin-project-lite 0.2.0", + "pin-project-lite", "tokio", ] [[package]] name = "toml" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" dependencies = [ "serde", ] [[package]] name = "tower-service" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.21" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" +checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "log", - "pin-project-lite 0.1.11", - "tracing-attributes", + "pin-project-lite", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tracing-core" version = "0.1.17" @@ -3921,22 +2984,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "tracing-futures" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" -dependencies = [ - "pin-project 0.4.27", - "tracing", -] - -[[package]] -name = "treeline" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" - [[package]] name = "try-lock" version = "0.2.3" @@ -3949,7 +2996,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24" dependencies = [ - "base64 0.13.0", + "base64", "byteorder", "bytes 1.0.1", "http", @@ -3957,7 +3004,7 @@ dependencies = [ "input_buffer", "log", "rand 0.8.3", - "sha-1 0.9.1", + "sha-1 0.9.4", "url", "utf-8", ] @@ -3983,9 +3030,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" [[package]] name = "ucd-trie" @@ -4010,27 +3057,27 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" dependencies = [ "matches", ] [[package]] name = "unicode-normalization" -version = "0.1.13" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" +checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" [[package]] name = "unicode-width" @@ -4064,10 +3111,11 @@ checksum = "7e33648dd74328e622c7be51f3b40a303c63f93e6fa5f08778b6203a4c25c20f" [[package]] name = "url" -version = "2.1.1" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" dependencies = [ + "form_urlencoded", "idna", "matches", "percent-encoding", @@ -4085,25 +3133,9 @@ dependencies = [ [[package]] name = "utf-8" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" - -[[package]] -name = "uuid" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" -dependencies = [ - "rand 0.7.3", - "serde", -] - -[[package]] -name = "vec-arena" -version = "1.0.0" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "vec_map" @@ -4113,9 +3145,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "void" @@ -4123,23 +3155,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" -dependencies = [ - "same-file", - "winapi", - "winapi-util", -] - [[package]] name = "want" version = "0.3.0" @@ -4152,9 +3167,9 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dafd0aac2818a94a34df0df1100a7356c493d8ede4393875fd0b5c51bb6bc80" +checksum = "332d47745e9a0c38636dbd454729b147d16bd1ed08ae67b3ab281c4506771054" dependencies = [ "bytes 1.0.1", "futures", @@ -4166,7 +3181,7 @@ dependencies = [ "mime_guess", "multipart", "percent-encoding", - "pin-project 1.0.1", + "pin-project", "scoped-tls", "serde", "serde_json", @@ -4177,7 +3192,6 @@ dependencies = [ "tokio-util", "tower-service", "tracing", - "tracing-futures", ] [[package]] @@ -4194,19 +3208,19 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" +checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" +checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae" dependencies = [ "bumpalo", "lazy_static", @@ -4217,23 +3231,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" -dependencies = [ - "cfg-if 0.1.10", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" +checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4241,9 +3243,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" +checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c" dependencies = [ "proc-macro2", "quote", @@ -4254,29 +3256,20 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" +checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489" [[package]] name = "web-sys" -version = "0.3.45" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" +checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "wepoll-sys" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff" -dependencies = [ - "cc", -] - [[package]] name = "winapi" version = "0.3.9" @@ -4293,15 +3286,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -4330,9 +3314,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" +checksum = "dc9c39e6d503229ffa00cc2954af4a751e6bbedf2a2c18e856eb3ece93d32495" dependencies = [ "proc-macro2", "syn", @@ -4341,18 +3325,18 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" +checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1" dependencies = [ "proc-macro2", "quote", @@ -4362,18 +3346,18 @@ dependencies = [ [[package]] name = "zstd" -version = "0.5.3+zstd.1.4.5" +version = "0.5.4+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b32eaf771efa709e8308605bbf9319bf485dc1503179ec0469b611937c0cd8" +checksum = "69996ebdb1ba8b1517f61387a883857818a66c8a295f487b1ffd8fd9d2c82910" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "2.0.5+zstd.1.4.5" +version = "2.0.6+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfb642e0d27f64729a639c52db457e0ae906e7bc6f5fe8f5c453230400f1055" +checksum = "98aa931fb69ecee256d44589d19754e61851ae4769bf963b385119b1cc37a49e" dependencies = [ "libc", "zstd-sys", @@ -4381,9 +3365,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.4.17+zstd.1.4.5" +version = "1.4.18+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89249644df056b522696b1bb9e7c18c87e8ffa3e2f0dc3b0155875d6498f01b" +checksum = "a1e6e8778706838f43f771d80d37787cb2fe06dafe89dd3aebaf6721b9eaec81" dependencies = [ "cc", "glob", diff --git a/Cargo.toml b/Cargo.toml index aa040bba0..775733725 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,23 +33,8 @@ members = [ "neon/native", "rust-bins/duniter-dbex", "rust-bins/xtask", - "rust-libs/dubp-wot", - "rust-libs/duniter-conf", - "rust-libs/duniter-dbs", - "rust-libs/duniter-bc-reader", - "rust-libs/duniter-dbs-write-ops", - "rust-libs/duniter-mempools", - "rust-libs/duniter-module", "rust-libs/duniter-server", - "rust-libs/duniter-global", - "rust-libs/modules/gva", - "rust-libs/modules/gva/bca", - "rust-libs/modules/gva/bca/types", - "rust-libs/modules/gva/dbs-reader", - "rust-libs/modules/gva/gql", - "rust-libs/modules/gva/indexer", "rust-libs/tests/duniter-integration-tests", - "rust-libs/tools/kv_typed" ] [patch.crates-io] diff --git a/deny.toml b/deny.toml index 0ed91ca7b..655111165 100644 --- a/deny.toml +++ b/deny.toml @@ -61,4 +61,3 @@ version = "0.3.1" [sources] unknown-registry = "deny" -unknown-git = "deny" diff --git a/neon/native/Cargo.toml b/neon/native/Cargo.toml index 060c52e94..c0de6dee9 100644 --- a/neon/native/Cargo.toml +++ b/neon/native/Cargo.toml @@ -18,7 +18,7 @@ neon-build = "0.4.0" bincode = "1.2.1" bs58 = "0.3.0" dubp = { version = "0.51.0", features = ["duniter"] } -dubp-wot = { path = "../../rust-libs/dubp-wot" } +dubp-wot = { git = "https://git.duniter.org/nodes/rust/duniter-core" } duniter-server = { path = "../../rust-libs/duniter-server" } flate2 = "1.0.16" flexi_logger = { version = "=0.16.0", default-features = false, features = ["compress"] } diff --git a/rust-bins/duniter-dbex/Cargo.toml b/rust-bins/duniter-dbex/Cargo.toml index 3b923fee4..b018a8747 100644 --- a/rust-bins/duniter-dbex/Cargo.toml +++ b/rust-bins/duniter-dbex/Cargo.toml @@ -23,10 +23,9 @@ arrayvec = "0.5.1" comfy-table = "2.1.0" dirs = "3.0.1" dubp = { version = "0.51.0", features = ["duniter"] } -duniter-dbs = { path = "../../rust-libs/duniter-dbs", default-features = false, features = ["explorer", "leveldb_backend", "sled_backend"] } -duniter-dbs-write-ops = { path = "../../rust-libs/duniter-dbs-write-ops", default-features = false, features = ["explorer", "leveldb_backend", "sled_backend"] } -duniter-gva-db = { path = "../../rust-libs/modules/gva/db", default-features = false, features = ["explorer", "leveldb_backend"] } -duniter-gva-indexer = { path = "../../rust-libs/modules/gva/indexer" } +duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core", features = ["bc-writer", "explorer", "leveldb_backend"] } +duniter-gva-db = { git = "https://git.duniter.org/nodes/rust/modules/duniter-gva", default-features = false, features = ["explorer", "leveldb_backend"] } +duniter-gva-indexer = { git = "https://git.duniter.org/nodes/rust/modules/duniter-gva" } fast-threadpool = "0.2.3" flume = "0.10.0" once_cell = "1.5.2" diff --git a/rust-bins/duniter-dbex/src/export_bc.rs b/rust-bins/duniter-dbex/src/export_bc.rs index 007880843..a07b46651 100644 --- a/rust-bins/duniter-dbex/src/export_bc.rs +++ b/rust-bins/duniter-dbex/src/export_bc.rs @@ -14,7 +14,7 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. use crate::*; -use duniter_dbs::{ +use duniter_core::dbs::{ databases::bc_v1::{BcV1Db, BcV1DbReadable}, kv_typed::prelude::Backend, }; diff --git a/rust-bins/duniter-dbex/src/main.rs b/rust-bins/duniter-dbex/src/main.rs index 90cf5770c..977d8df5c 100644 --- a/rust-bins/duniter-dbex/src/main.rs +++ b/rust-bins/duniter-dbex/src/main.rs @@ -32,17 +32,17 @@ use self::cli::{Database, Opt, OutputFormat, SubCommand}; use self::stringify_json_value::stringify_json_value; use anyhow::anyhow; use comfy_table::Table; -use duniter_dbs::databases::{ +use duniter_core::dbs::databases::{ bc_v1::{BcV1Db, BcV1DbWritable}, bc_v2::{BcV2Db, BcV2DbWritable}, network_v1::{NetworkV1Db, NetworkV1DbWritable}, txs_mp_v2::{TxsMpV2Db, TxsMpV2DbWritable}, }; -use duniter_dbs::kv_typed::prelude::*; -use duniter_dbs::prelude::*; -use duniter_dbs::regex::Regex; -use duniter_dbs::serde_json::{Map, Value}; -use duniter_dbs::smallvec::{smallvec, SmallVec}; +use duniter_core::dbs::kv_typed::prelude::*; +use duniter_core::dbs::prelude::*; +use duniter_core::dbs::regex::Regex; +use duniter_core::dbs::serde_json::{Map, Value}; +use duniter_core::dbs::smallvec::{smallvec, SmallVec}; use duniter_gva_db::{GvaV1Db, GvaV1DbWritable}; use rayon::prelude::*; use std::{ diff --git a/rust-bins/duniter-dbex/src/migrate.rs b/rust-bins/duniter-dbex/src/migrate.rs index a3312ae1a..483271fa3 100644 --- a/rust-bins/duniter-dbex/src/migrate.rs +++ b/rust-bins/duniter-dbex/src/migrate.rs @@ -18,7 +18,7 @@ use dubp::{ block::parser::parse_json_block_from_serde_value, block::parser::ParseJsonBlockError, block::prelude::DubpBlockTrait, block::DubpBlock, common::prelude::BlockNumber, }; -use duniter_dbs::{databases::bc_v1::BcV1DbReadable, FileBackend}; +use duniter_core::dbs::{databases::bc_v1::BcV1DbReadable, FileBackend}; use fast_threadpool::{ThreadPool, ThreadPoolConfig}; use std::{ops::Deref, path::PathBuf}; @@ -26,7 +26,7 @@ const CHUNK_SIZE: usize = 250; pub(crate) fn migrate(profile_path: PathBuf) -> anyhow::Result<()> { let start_time = Instant::now(); - let (bc_db, shared_dbs) = duniter_dbs::open_dbs(Some(profile_path.as_path()))?; + let (bc_db, shared_dbs) = duniter_core::dbs::open_dbs(Some(profile_path.as_path()))?; let gva_db = duniter_gva_indexer::get_gva_db_rw(Some(profile_path.as_path())); // Clear bc_db and gva_db @@ -118,7 +118,7 @@ fn migrate_inner( Ok::<_, KvError>(()) }) .expect("gva:apply_chunk: dbs pool disconnected"); - current = Some(duniter_dbs_write_ops::apply_block::apply_chunk( + current = Some(duniter_core::dbs_write_ops::apply_block::apply_chunk( bc_db, current, &dbs_pool, chunk, None, )?); gva_handle diff --git a/rust-libs/dubp-wot/Cargo.toml b/rust-libs/dubp-wot/Cargo.toml deleted file mode 100644 index 5a060429e..000000000 --- a/rust-libs/dubp-wot/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "dubp-wot" -version = "0.11.0" -authors = ["nanocryk <nanocryk@duniter.org>", "elois <elois@duniter.org>"] -description = "Makes Web of Trust computations for the Duniter project." -repository = "https://git.duniter.org/nodes/typescript/duniter" -readme = "README.md" -keywords = ["duniter", "wot", "trust"] -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -log = "0.4.8" -rayon = "1.3.0" -serde = { version = "1.0.105", features = ["derive"] } - -[dev-dependencies] -bincode = "1.2.0" - -[features] diff --git a/rust-libs/dubp-wot/README.md b/rust-libs/dubp-wot/README.md deleted file mode 100644 index 2d3dcdfc4..000000000 --- a/rust-libs/dubp-wot/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# wot - -`dubp-wot` is a crate making "Web of Trust" computations for -the [Duniter] project. - -[Duniter]: https://duniter.org/en/ - -## How to use it - -You can add `dubp-wot` as a `cargo` dependency in your Rust project. diff --git a/rust-libs/dubp-wot/src/data/mod.rs b/rust-libs/dubp-wot/src/data/mod.rs deleted file mode 100644 index eddc11e19..000000000 --- a/rust-libs/dubp-wot/src/data/mod.rs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Provide data structures to manage web of trusts. -//! `LegacyWebOfTrust` is almost a translation of the legacy C++ coden while -//! `RustyWebOfTrust` is a brand new implementation with a more "rusty" style. - -pub mod rusty; - -use serde::de::{self, Deserialize, DeserializeOwned, Deserializer, Visitor}; -use serde::{Serialize, Serializer}; -use std::{ - fmt::{self, Debug}, - io::Write, -}; - -/// Wrapper for a node id. -#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct WotId(pub usize); - -impl Serialize for WotId { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - serializer.serialize_u32(self.0 as u32) - } -} - -struct WotIdVisitor; - -impl<'de> Visitor<'de> for WotIdVisitor { - type Value = WotId; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("an integer between -2^31 and 2^31") - } - - fn visit_u8<E>(self, value: u8) -> Result<WotId, E> - where - E: de::Error, - { - Ok(WotId(value as usize)) - } - - fn visit_u32<E>(self, value: u32) -> Result<WotId, E> - where - E: de::Error, - { - Ok(WotId(value as usize)) - } - - fn visit_u64<E>(self, value: u64) -> Result<WotId, E> - where - E: de::Error, - { - use std::usize; - if value >= usize::MIN as u64 && value <= usize::MAX as u64 { - Ok(WotId(value as usize)) - } else { - Err(E::custom(format!("u32 out of range: {}", value))) - } - } -} - -impl<'de> Deserialize<'de> for WotId { - fn deserialize<D>(deserializer: D) -> Result<WotId, D::Error> - where - D: Deserializer<'de>, - { - deserializer.deserialize_u32(WotIdVisitor) - } -} - -/// Results of a certification, with the current certification count -/// of the destination as parameter. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum NewLinkResult { - /// Certification worked. - Ok(usize), - /// All available certifications has been used. - AllCertificationsUsed(usize), - /// Unknown source. - UnknownSource(), - /// Unknown target. - UnknownTarget(), - /// Self linking is forbidden. - SelfLinkingForbidden(), -} - -/// Results of a certification removal, with the current certification count -/// of the destination as parameter. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum RemLinkResult { - /// Certification has been removed. - Removed(usize), - /// Requested certification doesn't exist. - UnknownCert(usize), - /// Unknown source. - UnknownSource(), - /// Unknown target. - UnknownTarget(), -} - -/// Results of a certification test. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum HasLinkResult { - /// Both nodes are known, here is the result. - Link(bool), - /// Unknown source. - UnknownSource(), - /// Unknown target. - UnknownTarget(), -} - -/// Trait for a Web Of Trust. -/// Allow to provide other implementations of the `WoT` logic instead of the legacy C++ -/// translated one. -pub trait WebOfTrust: Clone + Debug + Default + DeserializeOwned + Send + Serialize + Sync { - /// Create a new Web of Trust with the maximum of links a node can issue. - fn new(max_links: usize) -> Self; - - /// Clear Web of Trust datas - fn clear(&mut self); - - /// Get the maximum number of links per user. - fn get_max_link(&self) -> usize; - - /// Set the maximum number of links per user. - fn set_max_link(&mut self, max_link: usize); - - /// Add a new node. - fn add_node(&mut self) -> WotId; - - /// Remove the last node. - /// Returns `None` if the WoT was empty, otherwise new top node id. - fn rem_node(&mut self) -> Option<WotId>; - - /// Get the size of the WoT. - fn size(&self) -> usize; - - /// Check if given node is enabled. - /// Returns `None` if this node doesn't exist. - fn is_enabled(&self, id: WotId) -> Option<bool>; - - /// Set the enabled state of given node. - /// Returns `Null` if this node doesn't exist, `enabled` otherwise. - fn set_enabled(&mut self, id: WotId, enabled: bool) -> Option<bool>; - - /// Get enabled node array. - fn get_enabled(&self) -> Vec<WotId>; - - /// Get disabled node array. - fn get_disabled(&self) -> Vec<WotId>; - - /// Try to add a link from the source to the target. - fn add_link(&mut self, source: WotId, target: WotId) -> NewLinkResult; - - /// Try to remove a link from the source to the target. - fn rem_link(&mut self, source: WotId, target: WotId) -> RemLinkResult; - - /// Test if there is a link from the source to the target. - fn has_link(&self, source: WotId, target: WotId) -> HasLinkResult; - - /// Get the list of links source for this target. - /// Returns `None` if this node doesn't exist. - fn get_links_source(&self, target: WotId) -> Option<Vec<WotId>>; - - /// Get the number of issued links by a node. - /// Returns `None` if this node doesn't exist. - fn issued_count(&self, id: WotId) -> Option<usize>; - - /// Test if a node is a sentry. - fn is_sentry(&self, node: WotId, sentry_requirement: usize) -> Option<bool>; - - /// Get sentries array. - fn get_sentries(&self, sentry_requirement: usize) -> Vec<WotId>; - - /// Get non sentries array. - fn get_non_sentries(&self, sentry_requirement: usize) -> Vec<WotId>; - - /// Dump wot - fn dump<W: Write>(&self, output: &mut W) -> std::io::Result<()>; -} diff --git a/rust-libs/dubp-wot/src/data/rusty.rs b/rust-libs/dubp-wot/src/data/rusty.rs deleted file mode 100644 index 398027350..000000000 --- a/rust-libs/dubp-wot/src/data/rusty.rs +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Experimental implementation of the Web of Trust in a more "rusty" style. - -use super::{HasLinkResult, NewLinkResult, RemLinkResult}; -use crate::WebOfTrust; -use crate::WotId; -use rayon::prelude::*; -use serde::{Deserialize, Serialize}; -use std::collections::HashSet; - -/// A node in the `WoT` graph. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -struct Node { - /// Is this node enabled ? - enabled: bool, - /// Set of links this node is the target. - links_source: HashSet<WotId>, - /// Number of links the node issued. - issued_count: usize, -} - -impl Node { - /// Create a new node. - pub fn new() -> Node { - Node { - enabled: true, - links_source: HashSet::new(), - issued_count: 0, - } - } -} - -/// A more idiomatic implementation of a Web of Trust. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct RustyWebOfTrust { - /// List of nodes in the WoT. - nodes: Vec<Node>, - /// Maximum number of links a node can issue. - max_links: usize, -} - -impl Default for RustyWebOfTrust { - fn default() -> RustyWebOfTrust { - RustyWebOfTrust { - nodes: Vec::new(), - max_links: 4_000_000_000, - } - } -} - -impl WebOfTrust for RustyWebOfTrust { - fn new(max_links: usize) -> RustyWebOfTrust { - RustyWebOfTrust { - nodes: vec![], - max_links, - } - } - - fn clear(&mut self) { - self.nodes = Vec::new(); - } - - fn get_max_link(&self) -> usize { - self.max_links - } - - fn set_max_link(&mut self, max_links: usize) { - self.max_links = max_links; - } - - fn add_node(&mut self) -> WotId { - self.nodes.push(Node::new()); - WotId(self.nodes.len() - 1) - } - - fn rem_node(&mut self) -> Option<WotId> { - if !self.nodes.is_empty() { - self.nodes.pop(); - Some(WotId(self.nodes.len())) - } else { - None - } - } - - fn size(&self) -> usize { - self.nodes.len() - } - - fn is_enabled(&self, id: WotId) -> Option<bool> { - self.nodes.get(id.0).map(|n| n.enabled) - } - - fn set_enabled(&mut self, id: WotId, enabled: bool) -> Option<bool> { - self.nodes - .get_mut(id.0) - .map(|n| n.enabled = enabled) - .map(|_| enabled) - } - - fn get_enabled(&self) -> Vec<WotId> { - self.nodes - .par_iter() - .enumerate() - .filter(|&(_, n)| n.enabled) - .map(|(i, _)| WotId(i)) - .collect() - } - - fn get_disabled(&self) -> Vec<WotId> { - self.nodes - .par_iter() - .enumerate() - .filter(|&(_, n)| !n.enabled) - .map(|(i, _)| WotId(i)) - .collect() - } - - fn add_link(&mut self, source: WotId, target: WotId) -> NewLinkResult { - if source == target { - NewLinkResult::SelfLinkingForbidden() - } else if source.0 >= self.size() { - NewLinkResult::UnknownSource() - } else if target.0 >= self.size() { - NewLinkResult::UnknownTarget() - } else if self.nodes[source.0].issued_count >= self.max_links { - NewLinkResult::AllCertificationsUsed(self.nodes[target.0].links_source.len()) - } else { - self.nodes[source.0].issued_count += 1; - self.nodes[target.0].links_source.insert(source); - NewLinkResult::Ok(self.nodes[target.0].links_source.len()) - } - } - - fn rem_link(&mut self, source: WotId, target: WotId) -> RemLinkResult { - if source.0 >= self.size() { - RemLinkResult::UnknownSource() - } else if target.0 >= self.size() { - RemLinkResult::UnknownTarget() - } else if !self.nodes[target.0].links_source.contains(&source) { - RemLinkResult::UnknownCert(self.nodes[target.0].links_source.len()) - } else { - self.nodes[source.0].issued_count -= 1; - self.nodes[target.0].links_source.remove(&source); - RemLinkResult::Removed(self.nodes[target.0].links_source.len()) - } - } - - fn has_link(&self, source: WotId, target: WotId) -> HasLinkResult { - if source.0 >= self.size() { - HasLinkResult::UnknownSource() - } else if target.0 >= self.size() { - HasLinkResult::UnknownTarget() - } else { - HasLinkResult::Link(self.nodes[target.0].links_source.contains(&source)) - } - } - - fn get_links_source(&self, target: WotId) -> Option<Vec<WotId>> { - self.nodes - .get(target.0) - .map(|n| n.links_source.iter().cloned().collect()) - } - - fn issued_count(&self, id: WotId) -> Option<usize> { - self.nodes.get(id.0).map(|n| n.issued_count) - } - - fn is_sentry(&self, node: WotId, sentry_requirement: usize) -> Option<bool> { - if node.0 >= self.size() { - return None; - } - - let node = &self.nodes[node.0]; - - Some( - node.enabled - && node.issued_count >= sentry_requirement - && node.links_source.len() >= sentry_requirement, - ) - } - - fn get_sentries(&self, sentry_requirement: usize) -> Vec<WotId> { - self.nodes - .par_iter() - .enumerate() - .filter(|&(_, n)| { - n.enabled - && n.issued_count >= sentry_requirement - && n.links_source.len() >= sentry_requirement - }) - .map(|(i, _)| WotId(i)) - .collect() - } - - fn get_non_sentries(&self, sentry_requirement: usize) -> Vec<WotId> { - self.nodes - .par_iter() - .enumerate() - .filter(|&(_, n)| { - n.enabled - && (n.issued_count < sentry_requirement - || n.links_source.len() < sentry_requirement) - }) - .map(|(i, _)| WotId(i)) - .collect() - } - - fn dump<W: std::io::Write>(&self, output: &mut W) -> std::io::Result<()> { - writeln!(output, "max_links={}", self.max_links)?; - writeln!(output, "nodes_count={}", self.nodes.len())?; - for (node_id, node) in self.nodes.iter().enumerate() { - write!(output, "{:03}: ", node_id)?; - if !node.enabled { - write!(output, "disabled ")?; - } - // dump sources - write!(output, "[")?; - let mut sorted_sources = node.links_source.iter().copied().collect::<Vec<WotId>>(); - sorted_sources.sort_unstable(); - let mut remaining_sources = sorted_sources.len(); - for source in &sorted_sources { - if remaining_sources == 1 { - write!(output, "{}", source.0)?; - } else { - write!(output, "{}, ", source.0)?; - remaining_sources -= 1; - } - } - writeln!(output, "]")?; - } - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::generic_wot_test; - - #[test] - fn wot_tests() { - generic_wot_test::<RustyWebOfTrust>(); - } -} diff --git a/rust-libs/dubp-wot/src/lib.rs b/rust-libs/dubp-wot/src/lib.rs deleted file mode 100644 index dbfc71b4b..000000000 --- a/rust-libs/dubp-wot/src/lib.rs +++ /dev/null @@ -1,561 +0,0 @@ -// Copyright (C) 2017-2020 The AXIOM TEAM Association. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! `wot` is a crate making "Web of Trust" computations for -//! the [Duniter] project. -//! -//! [Duniter]: https://duniter.org/ -//! -//! It defines a trait representing a Web of Trust and allow to do calculations on it. -//! -//! It also contains an "legacy" implementation translated from the original C++ code. -//! -//! Web of Trust tests are translated from [duniter/wot Javascript test][js-tests]. -//! -//! [js-tests]: https://github.com/duniter/wot/blob/master/wotcpp/webOfTrust.cpp - -#![deny( - clippy::unwrap_used, - missing_docs, - missing_debug_implementations, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unsafe_code, - unstable_features, - unused_import_braces, - unused_qualifications -)] - -pub mod data; -pub mod operations; - -pub use crate::data::{WebOfTrust, WotId}; - -#[cfg(test)] -mod tests { - use super::*; - use crate::data::*; - use crate::operations::centrality::*; - use crate::operations::distance::*; - use crate::operations::path::*; - use std::{io::Read, io::Write, path::Path}; - - fn read_bin_file(file_path: &Path) -> Result<Vec<u8>, std::io::Error> { - let mut file = std::fs::File::open(file_path)?; - if file.metadata()?.len() == 0 { - Ok(vec![]) - } else { - let mut bin_datas = Vec::new(); - file.read_to_end(&mut bin_datas)?; - - Ok(bin_datas) - } - } - - fn write_bin_file(file_path: &Path, datas: &[u8]) -> Result<(), std::io::Error> { - let mut file = std::fs::File::create(file_path)?; - file.write_all(datas)?; - - Ok(()) - } - - /// Test translated from https://github.com/duniter/wot/blob/master/tests/test.js - /// - /// Clone and file tests are not included in this generic test and should be done in - /// the implementation test. - #[allow(clippy::cognitive_complexity)] - pub fn generic_wot_test<W>() - where - W: WebOfTrust + Sync, - { - let centralities_calculator = UlrikBrandesCentralityCalculator {}; - let distance_calculator = RustyDistanceCalculator {}; - let path_finder = RustyPathFinder {}; - let mut wot = W::new(3); - - // should have an initial size of 0 - assert_eq!(wot.size(), 0); - - // should return `None()` if testing `is_enabled()` with out-of-bounds node - assert_eq!(wot.is_enabled(WotId(0)), None); - assert_eq!(wot.is_enabled(WotId(23)), None); - - // should give nomber 0 if we add a node - // - add a node - assert_eq!(wot.add_node(), WotId(0)); - assert_eq!(wot.size(), 1); - assert_eq!(wot.get_disabled().len(), 0); - - // delete top node (return new top node id) - assert_eq!(wot.rem_node(), Some(WotId(0))); - assert_eq!(wot.size(), 0); - - // readd node - assert_eq!(wot.add_node(), WotId(0)); - - // - add another - assert_eq!(wot.add_node(), WotId(1)); - assert_eq!(wot.size(), 2); - assert_eq!(wot.get_disabled().len(), 0); - - // - add 10 nodes - for i in 0..10 { - assert_eq!(wot.add_node(), WotId(i + 2)); - } - - assert_eq!(wot.size(), 12); - - // shouldn't be able to self cert - assert_eq!( - wot.add_link(WotId(0), WotId(0)), - NewLinkResult::SelfLinkingForbidden() - ); - - // should add certs only in the boundaries of max_cert - assert_eq!(wot.add_link(WotId(0), WotId(1)), NewLinkResult::Ok(1)); - assert_eq!(wot.add_link(WotId(0), WotId(2)), NewLinkResult::Ok(1)); - assert_eq!(wot.add_link(WotId(0), WotId(3)), NewLinkResult::Ok(1)); - assert_eq!( - wot.add_link(WotId(0), WotId(4)), - NewLinkResult::AllCertificationsUsed(0) - ); - - assert_eq!(wot.get_max_link(), 3); - assert_eq!(wot.has_link(WotId(0), WotId(1)), HasLinkResult::Link(true)); - assert_eq!(wot.has_link(WotId(0), WotId(2)), HasLinkResult::Link(true)); - assert_eq!(wot.has_link(WotId(0), WotId(3)), HasLinkResult::Link(true)); - assert_eq!(wot.has_link(WotId(0), WotId(4)), HasLinkResult::Link(false)); - - wot.set_max_link(4); - assert_eq!(wot.get_max_link(), 4); - assert_eq!(wot.has_link(WotId(0), WotId(4)), HasLinkResult::Link(false)); - wot.add_link(WotId(0), WotId(4)); - assert_eq!(wot.has_link(WotId(0), WotId(4)), HasLinkResult::Link(true)); - wot.rem_link(WotId(0), WotId(1)); - wot.rem_link(WotId(0), WotId(2)); - wot.rem_link(WotId(0), WotId(3)); - wot.rem_link(WotId(0), WotId(4)); - - // false when not linked + test out of bounds - assert_eq!(wot.has_link(WotId(0), WotId(6)), HasLinkResult::Link(false)); - assert_eq!( - wot.has_link(WotId(23), WotId(0)), - HasLinkResult::UnknownSource() - ); - assert_eq!( - wot.has_link(WotId(2), WotId(53)), - HasLinkResult::UnknownTarget() - ); - - // created nodes should be enabled - assert_eq!(wot.is_enabled(WotId(0)), Some(true)); - assert_eq!(wot.is_enabled(WotId(1)), Some(true)); - assert_eq!(wot.is_enabled(WotId(2)), Some(true)); - assert_eq!(wot.is_enabled(WotId(3)), Some(true)); - assert_eq!(wot.is_enabled(WotId(11)), Some(true)); - - // should be able to disable some nodes - assert_eq!(wot.set_enabled(WotId(0), false), Some(false)); - assert_eq!(wot.set_enabled(WotId(1), false), Some(false)); - assert_eq!(wot.set_enabled(WotId(2), false), Some(false)); - assert_eq!(wot.get_disabled().len(), 3); - assert_eq!(wot.set_enabled(WotId(1), true), Some(true)); - - // node 0 and 2 should be disabled - assert_eq!(wot.is_enabled(WotId(0)), Some(false)); - assert_eq!(wot.is_enabled(WotId(1)), Some(true)); - assert_eq!(wot.is_enabled(WotId(2)), Some(false)); - assert_eq!(wot.is_enabled(WotId(3)), Some(true)); - // - set enabled again - assert_eq!(wot.set_enabled(WotId(0), true), Some(true)); - assert_eq!(wot.set_enabled(WotId(1), true), Some(true)); - assert_eq!(wot.set_enabled(WotId(2), true), Some(true)); - assert_eq!(wot.set_enabled(WotId(1), true), Some(true)); - assert_eq!(wot.get_disabled().len(), 0); - - // should not exist a link from 2 to 0 - assert_eq!(wot.has_link(WotId(2), WotId(0)), HasLinkResult::Link(false)); - - // should be able to add some links, cert count is returned - assert_eq!(wot.add_link(WotId(2), WotId(0)), NewLinkResult::Ok(1)); - assert_eq!(wot.add_link(WotId(4), WotId(0)), NewLinkResult::Ok(2)); - assert_eq!(wot.add_link(WotId(5), WotId(0)), NewLinkResult::Ok(3)); - - // should exist new links - /* WoT is: - * - * 2 --> 0 - * 4 --> 0 - * 5 --> 0 - */ - - assert_eq!(wot.has_link(WotId(2), WotId(0)), HasLinkResult::Link(true)); - assert_eq!(wot.has_link(WotId(4), WotId(0)), HasLinkResult::Link(true)); - assert_eq!(wot.has_link(WotId(5), WotId(0)), HasLinkResult::Link(true)); - assert_eq!(wot.has_link(WotId(2), WotId(1)), HasLinkResult::Link(false)); - - // should be able to remove some links - assert_eq!(wot.rem_link(WotId(4), WotId(0)), RemLinkResult::Removed(2)); - /* - * WoT is now: - * - * 2 --> 0 - * 5 --> 0 - */ - - // should exist less links - assert_eq!(wot.has_link(WotId(2), WotId(0)), HasLinkResult::Link(true)); - assert_eq!(wot.has_link(WotId(4), WotId(0)), HasLinkResult::Link(false)); - assert_eq!(wot.has_link(WotId(5), WotId(0)), HasLinkResult::Link(true)); - assert_eq!(wot.has_link(WotId(2), WotId(1)), HasLinkResult::Link(false)); - - // should successfully use distance rule - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 1, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(false) - ); - // => no because 2,4,5 have certified him - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 2, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(false) - ); - // => no because only member 2 has 2 certs, and has certified him - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 3, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(false) - ); - // => no because no member has issued 3 certifications - - // - we add links from member 3 - assert_eq!(wot.add_link(WotId(3), WotId(1)), NewLinkResult::Ok(1)); - assert_eq!(wot.add_link(WotId(3), WotId(2)), NewLinkResult::Ok(1)); - /* - * WoT is now: - * - * 2 --> 0 - * 5 --> 0 - * 3 --> 1 - * 3 --> 2 - */ - assert_eq!(wot.size(), 12); - assert_eq!(wot.get_sentries(1).len(), 1); - assert_eq!(wot.get_sentries(1)[0], WotId(2)); - assert_eq!(wot.get_sentries(2).len(), 0); - assert_eq!(wot.get_sentries(3).len(), 0); - assert_eq!(wot.get_non_sentries(1).len(), 11); // 12 - 1 - assert_eq!(wot.get_non_sentries(2).len(), 12); // 12 - 0 - assert_eq!(wot.get_non_sentries(3).len(), 12); // 12 - 0 - assert_eq!(path_finder.find_paths(&wot, WotId(3), WotId(0), 1).len(), 0); // KO - assert_eq!(path_finder.find_paths(&wot, WotId(3), WotId(0), 2).len(), 1); // It exists 3 -> 2 -> 0 - assert!(path_finder - .find_paths(&wot, WotId(3), WotId(0), 2) - .contains(&vec![WotId(3), WotId(2), WotId(0)])); - - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 1, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(false) - ); // OK : 2 -> 0 - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 2, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(false) - ); // OK : 2 -> 0 - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 3, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(false) - ); // OK : no stry \w 3 lnk - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 2, - step_max: 2, - x_percent: 1.0, - }, - ), - Ok(false) - ); // OK : 2 -> 0 - - wot.add_link(WotId(1), WotId(3)); - wot.add_link(WotId(2), WotId(3)); - - assert_eq!(wot.size(), 12); - assert_eq!(wot.get_sentries(1).len(), 3); - assert_eq!(wot.get_sentries(1)[0], WotId(1)); - assert_eq!(wot.get_sentries(1)[1], WotId(2)); - assert_eq!(wot.get_sentries(1)[2], WotId(3)); - - assert_eq!(wot.get_sentries(2).len(), 1); - assert_eq!(wot.get_sentries(2)[0], WotId(3)); - assert_eq!(wot.get_sentries(3).len(), 0); - assert_eq!(wot.get_non_sentries(1).len(), 9); // 12 - 3 - assert_eq!(wot.get_non_sentries(2).len(), 11); // 12 - 1 - assert_eq!(wot.get_non_sentries(3).len(), 12); // 12 - 0 - assert_eq!(path_finder.find_paths(&wot, WotId(3), WotId(0), 1).len(), 0); // KO - assert_eq!(path_finder.find_paths(&wot, WotId(3), WotId(0), 2).len(), 1); // It exists 3 -> 2 -> 0 - assert!(path_finder - .find_paths(&wot, WotId(3), WotId(0), 2) - .contains(&vec![WotId(3), WotId(2), WotId(0)])); - - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 1, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(true) - ); // KO : No path 3 -> 0 - /*assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 2, - step_max: 1, - x_percent: 1.0, - }, - ), - Some(true) - );*/ // KO : No path 3 -> 0 - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 3, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(false) - ); // OK : no stry \w 3 lnk - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 2, - step_max: 2, - x_percent: 1.0, - }, - ), - Ok(false) - ); // OK : 3 -> 2 -> 0 - - // should have 12 nodes - assert_eq!(wot.size(), 12); - - // delete top node (return new top node id) - assert_eq!(wot.rem_node(), Some(WotId(11))); - - // should have 11 nodes - assert_eq!(wot.size(), 11); - - // should work with member 3 disabled - // - with member 3 disabled (non-member) - assert_eq!(wot.set_enabled(WotId(3), false), Some(false)); - assert_eq!(wot.get_disabled().len(), 1); - assert_eq!( - distance_calculator.is_outdistanced( - &wot, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 2, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(false) - ); // OK : Disabled - - // Write wot in file - write_bin_file( - Path::new("test.wot"), - &bincode::serialize(&wot).expect("fail to serialize wot"), - ) - .expect("fail to write wot file"); - - let wot2_bin = read_bin_file(Path::new("test.wot")).expect("fail to read wot file"); - let wot2: W = bincode::deserialize(&wot2_bin).expect("fail to deserialize wot"); - - // Read wot from file - { - assert_eq!(wot.size(), wot2.size()); - assert_eq!( - wot.get_non_sentries(1).len(), - wot2.get_non_sentries(1).len() - ); - assert_eq!(wot.get_disabled().len(), wot2.get_disabled().len()); - assert_eq!(wot2.get_disabled().len(), 1); - assert_eq!(wot2.is_enabled(WotId(3)), Some(false)); - assert_eq!( - distance_calculator.is_outdistanced( - &wot2, - WotDistanceParameters { - node: WotId(0), - sentry_requirement: 2, - step_max: 1, - x_percent: 1.0, - }, - ), - Ok(false) - ); - } - - // Dump wot - let mut dump_wot2_chars = Vec::new(); - wot2.dump(&mut dump_wot2_chars).expect("fail to dump wot2"); - let dump_wot2_str = String::from_utf8(dump_wot2_chars).expect("invalid utf8 chars"); - assert_eq!( - dump_wot2_str, - "max_links=4 -nodes_count=11 -000: [2, 5] -001: [3] -002: [3] -003: disabled [1, 2] -004: [] -005: [] -006: [] -007: [] -008: [] -009: [] -010: [] -" - ); - - // Read g1_genesis wot - let wot3_bin = read_bin_file(Path::new("tests/g1_genesis.bin")) - .expect("fail to read g1_genesis wot file"); - let wot3: W = bincode::deserialize(&wot3_bin).expect("fail to deserialize g1_genesis wot"); - - // Check g1_genesis wot members_count - let members_count = wot3.get_enabled().len() as u64; - assert_eq!(members_count, 59); - - // Test compute_distance in g1_genesis wot - assert_eq!( - distance_calculator.compute_distance( - &wot3, - WotDistanceParameters { - node: WotId(37), - sentry_requirement: 3, - step_max: 5, - x_percent: 0.8, - }, - ), - Ok(WotDistance { - sentries: 48, - success: 48, - success_at_border: 3, - reached: 51, - reached_at_border: 3, - outdistanced: false, - },) - ); - - // Test betweenness centralities computation in g1_genesis wot - let centralities = centralities_calculator.betweenness_centralities(&wot3); - assert_eq!(centralities.len(), 59); - assert_eq!( - centralities, - vec![ - 148, 30, 184, 11, 60, 51, 40, 115, 24, 140, 47, 69, 16, 34, 94, 126, 151, 0, 34, - 133, 20, 103, 38, 144, 73, 523, 124, 23, 47, 17, 9, 64, 77, 281, 6, 105, 54, 0, - 111, 21, 6, 2, 0, 1, 47, 59, 28, 236, 0, 0, 0, 0, 60, 6, 0, 1, 8, 33, 169, - ] - ); - - // Test stress centralities computation in g1_genesis wot - let stress_centralities = centralities_calculator.stress_centralities(&wot3); - assert_eq!(stress_centralities.len(), 59); - assert_eq!( - stress_centralities, - vec![ - 848, 240, 955, 80, 416, 203, 290, 645, 166, 908, 313, 231, 101, 202, 487, 769, 984, - 0, 154, 534, 105, 697, 260, 700, 496, 1726, 711, 160, 217, 192, 89, 430, 636, 1276, - 41, 420, 310, 0, 357, 125, 50, 15, 0, 12, 275, 170, 215, 1199, 0, 0, 0, 0, 201, 31, - 0, 9, 55, 216, 865, - ] - ); - - // Test distance stress centralities computation in g1_genesis wot - let distance_stress_centralities = - centralities_calculator.distance_stress_centralities(&wot3, 5); - assert_eq!(distance_stress_centralities.len(), 59); - assert_eq!( - distance_stress_centralities, - vec![ - 848, 240, 955, 80, 416, 203, 290, 645, 166, 908, 313, 231, 101, 202, 487, 769, 984, - 0, 154, 534, 105, 697, 260, 700, 496, 1726, 711, 160, 217, 192, 89, 430, 636, 1276, - 41, 420, 310, 0, 357, 125, 50, 15, 0, 12, 275, 170, 215, 1199, 0, 0, 0, 0, 201, 31, - 0, 9, 55, 216, 865, - ] - ); - } -} diff --git a/rust-libs/dubp-wot/src/operations/centrality.rs b/rust-libs/dubp-wot/src/operations/centrality.rs deleted file mode 100644 index 933e43621..000000000 --- a/rust-libs/dubp-wot/src/operations/centrality.rs +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Provide a trait and implementations to find paths between nodes. - -use crate::data::WebOfTrust; -use crate::data::WotId; -use std::collections::{HashMap, VecDeque}; - -/// Find paths between 2 nodes of a `WebOfTrust`. -pub trait CentralitiesCalculator<T: WebOfTrust> { - /// Compute betweenness centrality of all members. - fn betweenness_centralities(&self, wot: &T) -> Vec<u64>; - /// Compute stress centrality of all members. - fn stress_centralities(&self, wot: &T) -> Vec<u64>; - /// Compute distance stress centrality of all members. - fn distance_stress_centralities(&self, wot: &T, step_max: usize) -> Vec<u64>; -} - -/// An implementation based on "Ulrik brandes" algo. -#[derive(Debug, Clone, Copy)] -pub struct UlrikBrandesCentralityCalculator; - -impl<T: WebOfTrust> CentralitiesCalculator<T> for UlrikBrandesCentralityCalculator { - fn betweenness_centralities(&self, wot: &T) -> Vec<u64> { - let wot_size = wot.size(); - let mut centralities = vec![0.0; wot_size]; - let enabled_nodes = wot.get_enabled(); - - // The source of any path belongs to enabled_nodes - for s in enabled_nodes.clone() { - let mut stack: Vec<WotId> = Vec::with_capacity(wot_size); - let mut paths: HashMap<WotId, Vec<WotId>> = HashMap::with_capacity(wot_size); - let mut sigma = vec![0.0; wot_size]; - let mut d: Vec<isize> = vec![-1; wot_size]; - let mut q: VecDeque<WotId> = VecDeque::with_capacity(wot_size); - - sigma[s.0] = 1.0; - d[s.0] = 0; - q.push_back(s); - while let Some(v) = q.pop_front() { - stack.push(v); - for w in wot.get_links_source(v).expect("v don't have any source !") { - // w found for the first time ? - if d[w.0] < 0 { - q.push_back(w); - d[w.0] = d[v.0] + 1; - } - // Shortest path to w via v - if d[w.0] == d[v.0] + 1 { - sigma[w.0] += sigma[v.0]; - paths.entry(w).or_insert_with(Vec::new).push(v); - } - } - } - let mut delta = vec![0.0; wot_size]; - // stack returns vertices in order of non-increasing distance from s - while let Some(w) = stack.pop() { - if paths.contains_key(&w) { - for v in paths.get(&w).expect("Not found w in p !") { - if enabled_nodes.contains(&w) { - delta[v.0] += (sigma[v.0] / sigma[w.0]) * (1.0 + delta[w.0]); - } else { - // If w not in enabled_nodes, no path can end at w - delta[v.0] += (sigma[v.0] / sigma[w.0]) * delta[w.0]; - } - } - } - if w != s { - centralities[w.0] += delta[w.0]; - } - } - } - centralities.into_iter().map(|c| c as u64).collect() - } - fn stress_centralities(&self, wot: &T) -> Vec<u64> { - let wot_size = wot.size(); - let mut centralities = vec![0.0; wot_size]; - let enabled_nodes = wot.get_enabled(); - - // The source of any path belongs to enabled_nodes - for s in enabled_nodes.clone() { - let mut stack: Vec<WotId> = Vec::with_capacity(wot_size); - let mut paths: HashMap<WotId, Vec<WotId>> = HashMap::with_capacity(wot_size); - let mut sigma = vec![0.0; wot_size]; - let mut d: Vec<isize> = vec![-1; wot_size]; - let mut q: VecDeque<WotId> = VecDeque::with_capacity(wot_size); - - sigma[s.0] = 1.0; - d[s.0] = 0; - q.push_back(s); - while let Some(v) = q.pop_front() { - stack.push(v); - for w in wot.get_links_source(v).expect("v don't have any source !") { - // w found for the first time ? - if d[w.0] < 0 { - q.push_back(w); - d[w.0] = d[v.0] + 1; - } - // Shortest path to w via v - if d[w.0] == d[v.0] + 1 { - sigma[w.0] += sigma[v.0]; - paths.entry(w).or_insert_with(Vec::new).push(v); - } - } - } - let mut delta = vec![0.0; wot_size]; - // stack returns vertices in order of non-increasing distance from s - while let Some(w) = stack.pop() { - if paths.contains_key(&w) { - for v in paths.get(&w).expect("Not found w in p !") { - if enabled_nodes.contains(&w) { - delta[v.0] += sigma[v.0] * (1.0 + (delta[w.0] / sigma[w.0])); - } else { - // If w not in enabled_nodes, no path can end at w - delta[v.0] += sigma[v.0] * (delta[w.0] / sigma[w.0]); - } - } - } - if w != s { - centralities[w.0] += delta[w.0]; - } - } - } - centralities.into_iter().map(|c| c as u64).collect() - } - fn distance_stress_centralities(&self, wot: &T, step_max: usize) -> Vec<u64> { - let wot_size = wot.size(); - let mut centralities = vec![0.0; wot_size]; - let enabled_nodes = wot.get_enabled(); - - // The source of any path belongs to enabled_nodes - for s in enabled_nodes.clone() { - let mut stack: Vec<WotId> = Vec::with_capacity(wot_size); - let mut paths: HashMap<WotId, Vec<WotId>> = HashMap::with_capacity(wot_size); - let mut sigma = vec![0.0; wot_size]; - let mut d: Vec<isize> = vec![-1; wot_size]; - let mut q: VecDeque<WotId> = VecDeque::with_capacity(wot_size); - - sigma[s.0] = 1.0; - d[s.0] = 0; - q.push_back(s); - while let Some(v) = q.pop_front() { - stack.push(v); - if d[v.0] < step_max as isize { - for w in wot.get_links_source(v).expect("v don't have any source !") { - // w found for the first time ? - if d[w.0] < 0 { - q.push_back(w); - d[w.0] = d[v.0] + 1; - } - // Shortest path to w via v - if d[w.0] == d[v.0] + 1 { - sigma[w.0] += sigma[v.0]; - paths.entry(w).or_insert_with(Vec::new).push(v); - } - } - } - } - let mut delta = vec![0.0; wot_size]; - // stack returns vertices in order of non-increasing distance from s - while let Some(w) = stack.pop() { - if paths.contains_key(&w) { - for v in paths.get(&w).expect("Not found w in p !") { - if enabled_nodes.contains(&w) { - delta[v.0] += sigma[v.0] * (1.0 + (delta[w.0] / sigma[w.0])); - } else { - // If w not in enabled_nodes, no path can end at w - delta[v.0] += sigma[v.0] * (delta[w.0] / sigma[w.0]); - } - } - } - if w != s { - centralities[w.0] += delta[w.0]; - } - } - } - centralities.into_iter().map(|c| c as u64).collect() - } -} diff --git a/rust-libs/dubp-wot/src/operations/density.rs b/rust-libs/dubp-wot/src/operations/density.rs deleted file mode 100644 index 76ae9a0f2..000000000 --- a/rust-libs/dubp-wot/src/operations/density.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Provide function to compute average density. - -use crate::data::WebOfTrust; - -/// Compute average density -pub fn calculate_average_density<T: WebOfTrust>(wot: &T) -> usize { - let enabled_members = wot.get_enabled(); - let enabled_members_count = enabled_members.len(); - let mut count_actives_links: usize = 0; - for member in &enabled_members { - count_actives_links += wot - .issued_count(*member) - .unwrap_or_else(|| panic!("Fail to get issued_count of wot_id {}", (*member).0)); - } - ((count_actives_links as f32 / enabled_members_count as f32) * 1_000.0) as usize -} diff --git a/rust-libs/dubp-wot/src/operations/distance.rs b/rust-libs/dubp-wot/src/operations/distance.rs deleted file mode 100644 index da6362e77..000000000 --- a/rust-libs/dubp-wot/src/operations/distance.rs +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Provide a trait and implementations to compute distances. - -use crate::data::WebOfTrust; -use crate::data::WotId; -use rayon::prelude::*; -use std::collections::HashSet; - -/// Paramters for `WoT` distance calculations -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct WotDistanceParameters { - /// Node from where distances are calculated. - pub node: WotId, - /// Links count received AND issued to be a sentry. - pub sentry_requirement: u32, - /// Currency parameter. - pub step_max: u32, - /// Currency parameter. - pub x_percent: f64, -} - -/// Results of `WebOfTrust::compute_distance`. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct WotDistance { - /// Sentries count - pub sentries: u32, - /// Success count - pub success: u32, - /// Succes at border count - pub success_at_border: u32, - /// Reached count - pub reached: u32, - /// Reached at border count - pub reached_at_border: u32, - /// Is the node outdistanced ? - pub outdistanced: bool, -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -/// Error occured when computing distance -pub enum DistanceError { - /// Node don't exist - NodeDontExist(WotId), -} - -/// Compute distance between nodes of a `WebOfTrust`. -pub trait DistanceCalculator<T: WebOfTrust> { - /// Compute distance between a node and the network. - /// Returns `None` if this node doesn't exist. - fn compute_distance( - &self, - wot: &T, - params: WotDistanceParameters, - ) -> Result<WotDistance, DistanceError>; - - /// Compute distances of all members - fn compute_distances( - &self, - wot: &T, - sentry_requirement: u32, - step_max: u32, - x_percent: f64, - ) -> Result<(usize, Vec<usize>, usize, Vec<usize>), DistanceError>; - - /// Test if a node is outdistanced in the network. - /// Returns `Node` if this node doesn't exist. - fn is_outdistanced( - &self, - wot: &T, - params: WotDistanceParameters, - ) -> Result<bool, DistanceError>; -} - -/// Calculate distances between 2 members in a `WebOfTrust`. -#[derive(Debug, Clone, Copy)] -pub struct RustyDistanceCalculator; - -impl<T: WebOfTrust + Sync> DistanceCalculator<T> for RustyDistanceCalculator { - fn compute_distance( - &self, - wot: &T, - params: WotDistanceParameters, - ) -> Result<WotDistance, DistanceError> { - let WotDistanceParameters { - node, - sentry_requirement, - step_max, - x_percent, - } = params; - - if node.0 >= wot.size() { - return Err(DistanceError::NodeDontExist(node)); - } - - let mut area = HashSet::new(); - area.insert(node); - let mut border = HashSet::new(); - border.insert(node); - - for _ in 0..step_max { - border = border - .par_iter() - .map(|&id| { - if let Some(links_source) = wot.get_links_source(id) { - Ok(links_source - .iter() - .filter(|source| !area.contains(source)) - .cloned() - .collect::<HashSet<_>>()) - } else { - Err(DistanceError::NodeDontExist(id)) - } - }) - .try_reduce(HashSet::new, |mut acc, sources| { - for source in sources { - acc.insert(source); - } - Ok(acc) - })?; - area.extend(border.iter()); - } - - let sentries: Vec<_> = wot.get_sentries(sentry_requirement as usize); - let mut success = area.iter().filter(|n| sentries.contains(n)).count() as u32; - let success_at_border = border.iter().filter(|n| sentries.contains(n)).count() as u32; - let mut sentries = sentries.len() as u32; - if wot - .is_sentry(node, sentry_requirement as usize) - .ok_or(DistanceError::NodeDontExist(node))? - { - sentries -= 1; - success -= 1; - } - - Ok(WotDistance { - sentries, - reached: area.len() as u32 - 1, - reached_at_border: border.len() as u32, - success, - success_at_border, - outdistanced: f64::from(success) < ((x_percent * f64::from(sentries)).trunc() - 1.0), - }) - } - - fn is_outdistanced( - &self, - wot: &T, - params: WotDistanceParameters, - ) -> Result<bool, DistanceError> { - Self::compute_distance(&self, wot, params).map(|result| result.outdistanced) - } - - fn compute_distances( - &self, - wot: &T, - sentry_requirement: u32, - step_max: u32, - x_percent: f64, - ) -> Result<(usize, Vec<usize>, usize, Vec<usize>), DistanceError> { - let members_count = wot.get_enabled().len(); - let mut distances = Vec::new(); - let mut average_distance: usize = 0; - let mut connectivities = Vec::new(); - let mut average_connectivity: usize = 0; - for i in 0..wot.size() { - let distance_datas: WotDistance = Self::compute_distance( - &self, - wot, - WotDistanceParameters { - node: WotId(i), - sentry_requirement, - step_max, - x_percent, - }, - )?; - let distance = ((f64::from(distance_datas.success) - / (x_percent * f64::from(distance_datas.sentries))) - * 100.0) as usize; - distances.push(distance); - average_distance += distance; - let connectivity = - ((f64::from(distance_datas.success - distance_datas.success_at_border) - / (x_percent * f64::from(distance_datas.sentries))) - * 100.0) as usize; - connectivities.push(connectivity); - average_connectivity += connectivity; - } - average_distance /= members_count; - average_connectivity /= members_count; - Ok(( - average_distance, - distances, - average_connectivity, - connectivities, - )) - } -} diff --git a/rust-libs/dubp-wot/src/operations/mod.rs b/rust-libs/dubp-wot/src/operations/mod.rs deleted file mode 100644 index e3fb53ca1..000000000 --- a/rust-libs/dubp-wot/src/operations/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Provide operation traits and implementations on `WebOfTrust` objects. - -pub mod centrality; -pub mod density; -pub mod distance; -pub mod path; diff --git a/rust-libs/dubp-wot/src/operations/path.rs b/rust-libs/dubp-wot/src/operations/path.rs deleted file mode 100644 index 5aef5149c..000000000 --- a/rust-libs/dubp-wot/src/operations/path.rs +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Provide a trait and implementations to find paths between nodes. - -use crate::data::WebOfTrust; -use crate::data::WotId; -use std::collections::HashSet; - -/// Find paths between 2 nodes of a `WebOfTrust`. -pub trait PathFinder<T: WebOfTrust> { - /// Get paths from one node to the other. - fn find_paths(&self, wot: &T, from: WotId, to: WotId, k_max: u32) -> Vec<Vec<WotId>>; -} - -/// A new "rusty-er" implementation of `WoT` path finding. -#[derive(Debug, Clone, Copy)] -pub struct RustyPathFinder; - -impl<T: WebOfTrust> PathFinder<T> for RustyPathFinder { - fn find_paths(&self, wot: &T, from: WotId, to: WotId, k_max: u32) -> Vec<Vec<WotId>> { - if from.0 >= wot.size() || to.0 >= wot.size() { - return vec![]; - } - - // 1. We explore the k_max area around `to`, and only remember backward - // links of the smallest distance. - - // Stores for each node its distance to `to` node and its backward links. - // By default all nodes are out of range (`k_max + 1`) and links are known. - let mut graph: Vec<(u32, Vec<WotId>)> = - (0..wot.size()).map(|_| (k_max + 1, vec![])).collect(); - // `to` node is at distance 0, and have no backward links. - graph[to.0] = (0, vec![]); - // Explored zone border. - let mut border = HashSet::new(); - border.insert(to); - - for distance in 1..=k_max { - let mut next_border = HashSet::new(); - - for node in border { - for source in &wot - .get_links_source(node) - .expect("links source must not be None") - { - match graph[source.0].0 { - path_distance if path_distance > distance => { - // shorter path, we replace - graph[source.0] = (distance, vec![node]); - next_border.insert(*source); - } - path_distance if path_distance == distance => { - // same length, we combine - graph[source.0].1.push(node); - next_border.insert(*source); - } - _ => unreachable!(), - } - } - } - - border = next_border; - } - - // 2. If `from` is found, we follow the backward links and build paths. - // For each path, we look at the last element sources and build new paths with them. - let mut paths = vec![vec![from]]; - - for _ in 1..=k_max { - let mut new_paths = vec![]; - - for path in &paths { - let node = path.last().expect("path should not be empty"); - - if node == &to { - // If path is complete, we keep it. - new_paths.push(path.clone()) - } else { - // If not complete we comlete paths - let sources = &graph[node.0]; - for source in &sources.1 { - let mut new_path = path.clone(); - new_path.push(*source); - new_paths.push(new_path); - } - } - } - - paths = new_paths; - } - - paths - } -} diff --git a/rust-libs/dubp-wot/tests/g1_genesis.bin b/rust-libs/dubp-wot/tests/g1_genesis.bin deleted file mode 100644 index d684f6197a5442ff4860dec581a65b19456a51d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3223 zcmcC!fB;5O2+hFDz`y`vGcqtRure?(urM$%urn|)XfQA^$TKi7STQg#C^9fGSTZm$ z@G~$la4|42FflMNa56A3h%+!Sm@qIf@Gvki@G&qj=rS-c$S^Q4h(OJTTLO{<87cv_ z0HhgYILH8yT96}@pca5E(t$e40%{@10+2&M7K=eG0hs~P%P0gQp%|nYWGKi$kgGwi z18D?l0{IN&1CU0LFF-y9ISk}`ki$R@0$Bvo4>FDs<YEv*nSp^p80syMVIT`Z8o3!5 z7}!7x7#JAft^nBpG6iHa$W)M%K?Z>|fD8et2Zb%jr63zYwt-v(G8p7ykZS~>;R{mB z2#ORC17tABFc2GLGsp`tIYvQ{C^Y6kwu4Lu`57b(G99ED6qp>)fCU9M$S{!YAe%w4 z1`2dgn1IxS^fAH=00kz<Ss*Wf6oWK_q8el%$Q2+>FbhEjg1iMX1Y{Y=Vvx5$;RLb- zWGN_EKo)?^1JUq+25ABbfD8ax2(nBP8u%bzf#euLfdgWIOacWcEHFWeK_-JVgIoo2 z3CMPkD?o;U^nfA)<QkC8(jWm)%z*+E#0D7%(gZRD#0P~3NF&H#kU=09fLsXjDu@qK z!w51R!~i9EP&xrAW@cbu0HqOCXqE!G66Al7Iz|`+<U~*!0oe-D1TqNZG?;4`LDqqE zfUE>*0)-yPT987Rvp{|Yg}ydOAv8mR<Uw3UkVX&#<{yw^kQm4|kgXtRf}9L83}i4! zEj)BVagXc*kaIzS12P>H|Dad^83GCnkOiR31u_T}vY_+=OOWsY0vRX;ElWTeK=G;o zO^qPiL0$yA0LB1GsxvS!$T2W5s4y@vfZ_|J38V;w;U<Ip0P+*aKcLV9MFl9xLCys^ z8)hIpL_uj6<Zh5#L7G9i2;_E<-#`HbOC_KH10@2Gp(r+j1V9lCvJqqe%r;PffLsDH z0IUHP3Luj}o(7o?%QYayApgJ=gIoj(MUX2%2?69fPy&G&4ss#bP>>;D2DBsw`440$ z$S_byf}#iHY*2!MMIj?7PC%MKnn5Ok6oJG*wu2OcoDK34C^dmx3o;bsB9I<X)PZPt zJ_RWTITa)bG7x4nC{ci101{^eMFWTd@(V}<C@MgTLH+`n4Du%^3_z{{*#Pn@$R(is z42n9C(_w~zVhH3SP|Sf65y)J)Yd{GDlu$sngIof#Kn+@%fMN<oF(_4mOps+@U;rrw zX#}M%P$~nt5Ud#FG!O&i43M=TCxR4%vKc7gK+XjP9LR|vb?{6LG9Bg|kf|U|AlpFx z1}g;V0x>`mASa+}04WC92vWlc@(73l3PBJXWGyI!K&F906qKSsP6LG|D1<<v334)W zVgTufI}c<!$ax@zAkTta0SW+kD8Z}-DFAs66v?2#0NJR|z`y`k2=fO>1IS4rD?y4t z;vgr0oC>l5#d=Ws0=XNMqCpV^G7XeU;0i$|fOLS|1d0%l2SEx!ZU%)E$o(KUgF+5u zGe|Amb0CvJ84_e7$Ocfx1lb5m(O`ujw}BWSYe60~XJB9eDFSH#X#^Pn@-RpZ+*FWN zAS*%E!<+<iCMZ-;6oQf_NCFg5AX7k^KoNuCPLLv)Bq)7@oCVShcPA(+K}LflK&cIs zO+jG_N_`-45QZmykOGj2phy5I0$B&r0MZQd6j(9Lv7lH1`5fd^P>g|m4zd;$3ZNhZ zX##72IYATJ5Cqu(@(jq`a77@iK&nBp0}2{YP=R6y6jUIEFhk&B3Ca;5MIcE%1_lO@ zLXZYfaDfbhdkUrqWHLx0C_RAu08$K62*U7o5l8_@AxILGMnR^76o4??M37Y=NpvTG zG=UU?FkCUn1W?j5g%+?N--8MlkP|=(K^Sg5ND;^bpl}6AfU*rn5P{+uWCBP5C>%iw zK(@d%!Gj3obC5eh9s;=;6s{l-f;56K+*(k!0OcD{Sq-uhWD+PU!HPf*1~EX10+c{N zg#<_;DE>i-1XMeKVh^MN<|%k{0i*zwKtSa%C|!aK0vQOh4P+3=-Jrw*5{Fl*pu!s@ j3DOMmASf4rf)JFlK(@gQ0BHib1Y`(^&7hI}4nzY0n4me& diff --git a/rust-libs/dubp-wot/tests/g1_genesis.bin.gz b/rust-libs/dubp-wot/tests/g1_genesis.bin.gz deleted file mode 100644 index 29617bd5ccb38685e0b06479fabfae0bb8394060..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 917 zcmb=JlRNEokdh-$tMTF(wgLwcw*z09*6mU~A-|^dhWoAZ`{_6MYG$6}37ER+wBPeN zb5!nrcJJGta_EuPjCGR})+S6pXm#*jvn|_g_G-Q`HfgrktlrJ32fGq>Cp0HiZt&gk zJ7K%;ggFb!8B$pEWja+ExVE%iF>he*(D)!S;f%vEp?X!v^$B|)KM;AK$X=Z?hq;7( zVWaZYl87};cPC6^lP=yMzvga=p~|Vg6`Cubvj}d{oy#)wa^%gPnkrp!i`2X7thc?_ zMV2_|pN#A<aXF*M;oT&vuzEqZ$;t`34O>0>Hp|`fSmXDIf&0=a2I)y*(i21?TPoNW z^d)Pt%wRBc-ri{0AF(87#*FID)HerHUIdv{&U1{5IIxd9!lEks_@Py^Jm<6=eyGR& zwpa9=c+s1Q^NZG8=-pwru{G#U<F58)LB?h$4|FEI`dRbs$*NcN5282Jb0lO%*@cNo zFX7hkud!S9E@aUYGXt^M*Y-*tnuV*@x^IbJH=8N*fTiUt#<i~}JKGC-nBQ-*WvQN+ zyf;m#J~Tyt_p0SfcQodmci&cH_Til6ohG;GF>Ad;Hf-H7Nn+8z<ToNFCaafzEjFFj zud?=HZdTAI!{<VxYXzs=J;%CTZr!U{0!w@^NP6ilT+18mdsejD=MifG>#w~>s&yN4 zrQLpQu3j+fvTca&0>%C#rIT!#&da=bI7fIV_g_v9>lu3{zdyj5eb7VOJb%;0V-?J` zYzMU4fBQaHSNd}xl0U25_P~b+Ii-3Hb07R^EC}v2fBUfE{ms^HD`ws7OEVl7Rwn4J zi!WZDp!aq9`MlknS=&_N681@EeR;NEsY*7}m)U)qCnN2(9)+Ddktu$8`;m*93vOk* z$sUfj{uTOYLs*~M<leusecYX`#!vm;aqniz`4cW=z3bRc|EB$gyPht1|4M7s*OQYM zr{qVUEmYpPSKl&Z-s71&&niyJwehdMQhNAUi0M}EebdfN>i8~n`|7h_hvxj1%_+ZP zK2u%j{RY3uhx9GaEw-)xw{MkDltQnUsk>Hbj;U<C%B!E68<$K!yW~t}<Kl15;g4Qi zx2SuxVs>=q9>Kad+tW49oVR?v?AlN7N6X)NB%RIv5U-LjKh4TaUFhc175jzSXIh73 zZ(n<)ufE|q=bFCObG@}&vX-oB>8txy4b<;uia?eSEomb87T%s4u)$d-(qw?gM&G lzbCAncSUw~>yhQ5sxggej4W!Q6Yu^1ciH|w<BSEC=K+cvz#9Mn diff --git a/rust-libs/duniter-bc-reader/Cargo.toml b/rust-libs/duniter-bc-reader/Cargo.toml deleted file mode 100644 index e89f4d627..000000000 --- a/rust-libs/duniter-bc-reader/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "duniter-bc-reader" -version = "0.1.0" -authors = ["elois <elois@duniter.org>"] -description = "Duniter DBs read operations" -repository = "https://git.duniter.org/nodes/typescript/duniter" -keywords = ["dubp", "duniter", "blockchain", "database"] -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -anyhow = "1.0.34" -duniter-dbs = { path = "../duniter-dbs" } -dubp = { version = "0.51.0", features = ["duniter"] } -resiter = "0.4.0" - -[dev-dependencies] -smallvec = { version = "1.4.0", features = ["serde", "write"] } diff --git a/rust-libs/duniter-bc-reader/src/lib.rs b/rust-libs/duniter-bc-reader/src/lib.rs deleted file mode 100644 index 222795751..000000000 --- a/rust-libs/duniter-bc-reader/src/lib.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -use dubp::crypto::hashs::Hash; -use duniter_dbs::{databases::bc_v2::BcV2DbReadable, kv_typed::prelude::*, HashKeyV2}; - -pub fn tx_exist<BcDb: BcV2DbReadable>(bc_db_ro: &BcDb, hash: Hash) -> KvResult<bool> { - bc_db_ro.txs_hashs().contains_key(&HashKeyV2(hash)) -} diff --git a/rust-libs/duniter-conf/Cargo.toml b/rust-libs/duniter-conf/Cargo.toml deleted file mode 100644 index f2b134f81..000000000 --- a/rust-libs/duniter-conf/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "duniter-conf" -version = "0.1.0" -authors = ["librelois <elois@duniter.org>"] -license = "AGPL-3.0" -edition = "2018" - -[dependencies] -dubp = { version = "0.51.0", features = ["duniter"] } -serde = { version = "1.0.105", features = ["derive"] } diff --git a/rust-libs/duniter-conf/src/gva_conf.rs b/rust-libs/duniter-conf/src/gva_conf.rs deleted file mode 100644 index 38825c561..000000000 --- a/rust-libs/duniter-conf/src/gva_conf.rs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - -use crate::*; - -#[derive(Clone, Debug, Default, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct GvaConf { - ip4: Option<Ipv4Addr>, - ip6: Option<Ipv6Addr>, - port: Option<u16>, - path: Option<String>, - subscriptions_path: Option<String>, - remote_host: Option<String>, - remote_port: Option<u16>, - remote_path: Option<String>, - remote_subscriptions_path: Option<String>, - remote_tls: Option<bool>, - whitelist: Option<Vec<IpAddr>>, -} - -impl GvaConf { - pub fn get_ip4(&self) -> Ipv4Addr { - self.ip4.unwrap_or(Ipv4Addr::LOCALHOST) - } - pub fn get_ip6(&self) -> Option<Ipv6Addr> { - self.ip6 - } - pub fn get_port(&self) -> u16 { - self.port.unwrap_or(30901) - } - pub fn get_path(&self) -> String { - if let Some(mut path) = self.path.clone() { - if path.starts_with('/') { - path.remove(0); - path - } else { - path - } - } else { - "localhost".to_owned() - } - } - pub fn get_subscriptions_path(&self) -> String { - if let Some(mut subscriptions_path) = self.subscriptions_path.clone() { - if subscriptions_path.starts_with('/') { - subscriptions_path.remove(0); - subscriptions_path - } else { - subscriptions_path - } - } else { - "localhost".to_owned() - } - } - pub fn get_remote_host(&self) -> String { - if let Some(ref remote_host) = self.remote_host { - remote_host.to_owned() - } else if let Some(ip6) = self.ip6 { - format!("{} [{}]", self.get_ip4(), ip6) - } else { - self.get_ip4().to_string() - } - } - pub fn get_remote_port(&self) -> u16 { - if let Some(remote_port) = self.remote_port { - remote_port - } else { - self.get_port() - } - } - pub fn get_remote_path(&self) -> String { - if let Some(ref remote_path) = self.remote_path { - remote_path.to_owned() - } else { - self.get_path() - } - } - pub fn get_remote_subscriptions_path(&self) -> String { - if let Some(ref remote_subscriptions_path) = self.remote_subscriptions_path { - remote_subscriptions_path.to_owned() - } else { - self.get_subscriptions_path() - } - } - pub fn get_remote_tls(&self) -> bool { - self.remote_tls.unwrap_or(false) - } - pub fn get_whitelist(&self) -> &[IpAddr] { - if let Some(ref whitelist) = self.whitelist { - whitelist - } else { - &[ - IpAddr::V4(Ipv4Addr::LOCALHOST), - IpAddr::V6(Ipv6Addr::LOCALHOST), - ] - } - } -} diff --git a/rust-libs/duniter-conf/src/lib.rs b/rust-libs/duniter-conf/src/lib.rs deleted file mode 100644 index 5038209c6..000000000 --- a/rust-libs/duniter-conf/src/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -pub mod gva_conf; - -use crate::gva_conf::GvaConf; -use dubp::crypto::keys::ed25519::Ed25519KeyPair; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug)] -pub struct DuniterConf { - pub gva: Option<GvaConf>, - pub self_key_pair: Ed25519KeyPair, - pub txs_mempool_size: usize, -} - -impl Default for DuniterConf { - fn default() -> Self { - DuniterConf { - gva: None, - self_key_pair: Ed25519KeyPair::generate_random().expect("fail to gen random keypair"), - txs_mempool_size: 0, - } - } -} - -/// Duniter mode -#[derive(Clone, Copy, Debug)] -#[non_exhaustive] -pub enum DuniterMode { - Start, - Sync, -} diff --git a/rust-libs/duniter-dbs-write-ops/Cargo.toml b/rust-libs/duniter-dbs-write-ops/Cargo.toml deleted file mode 100644 index 4b49787fd..000000000 --- a/rust-libs/duniter-dbs-write-ops/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = "duniter-dbs-write-ops" -version = "0.1.0" -authors = ["elois <elois@duniter.org>"] -description = "Duniter DBs write operations" -repository = "https://git.duniter.org/nodes/typescript/duniter" -keywords = ["dubp", "duniter", "blockchain", "database"] -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -chrono = "0.4.19" -dubp = { version = "0.51.0", features = ["duniter"] } -duniter-dbs = { path = "../duniter-dbs" } -duniter-global = { path = "../duniter-global" } -fast-threadpool = "0.2.3" -flume = "0.10" -log = "0.4.11" -resiter = "0.4.0" - -[dev-dependencies] -anyhow = "1.0.34" -duniter-dbs = { path = "../duniter-dbs", features = ["mem"] } -maplit = "1.0.2" -serde_json = "1.0.53" - -[features] -default = ["sled_backend"] - -explorer = ["duniter-dbs/explorer"] -leveldb_backend = ["duniter-dbs/leveldb_backend"] -sled_backend = ["duniter-dbs/sled_backend"] diff --git a/rust-libs/duniter-dbs-write-ops/src/apply_block.rs b/rust-libs/duniter-dbs-write-ops/src/apply_block.rs deleted file mode 100644 index 7d7e4511c..000000000 --- a/rust-libs/duniter-dbs-write-ops/src/apply_block.rs +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub fn apply_block( - bc_db: &BcV2Db<FileBackend>, - block: Arc<DubpBlockV10>, - current_opt: Option<BlockMetaV2>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - global_sender: &flume::Sender<GlobalBackGroundTaskMsg>, - throw_chainability: bool, -) -> KvResult<BlockMetaV2> { - if let Some(current) = current_opt { - if block.number().0 == current.number + 1 { - apply_block_inner(bc_db, dbs_pool, block, global_sender) - } else if throw_chainability { - Err(KvError::Custom( - format!( - "block #{} not chainable on current #{}", - block.number().0, - current.number - ) - .into(), - )) - } else { - Ok(current) - } - } else if block.number() == BlockNumber(0) { - apply_block_inner(bc_db, dbs_pool, block, global_sender) - } else { - Err(KvError::Custom( - "Try to apply non genesis block on empty blockchain".into(), - )) - } -} - -#[inline(always)] -pub fn apply_chunk( - bc_db: &BcV2Db<FileBackend>, - current_opt: Option<BlockMetaV2>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - blocks: Arc<[DubpBlockV10]>, - global_sender: Option<&flume::Sender<GlobalBackGroundTaskMsg>>, -) -> KvResult<BlockMetaV2> { - verify_chunk_chainability(current_opt, &blocks)?; - apply_chunk_inner(bc_db, dbs_pool, blocks, global_sender) -} - -fn verify_chunk_chainability( - current_opt: Option<BlockMetaV2>, - blocks: &[DubpBlockV10], -) -> KvResult<()> { - if let Some(mut current) = current_opt { - for block in blocks { - if block.number().0 == current.number + 1 { - current.number += 1; - } else { - return Err(KvError::Custom( - format!( - "block #{} not chainable on current #{}", - blocks[0].number().0, - current.number - ) - .into(), - )); - } - } - Ok(()) - } else if blocks[0].number() == BlockNumber(0) { - let mut current_number = 0; - for block in &blocks[1..] { - if block.number().0 == current_number + 1 { - current_number += 1; - } else { - return Err(KvError::Custom( - format!( - "block #{} not chainable on current #{}", - block.number().0, - current_number - ) - .into(), - )); - } - } - Ok(()) - } else { - Err(KvError::Custom( - "Try to apply non genesis block on empty blockchain".into(), - )) - } -} - -fn apply_block_inner( - bc_db: &BcV2Db<FileBackend>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - block: Arc<DubpBlockV10>, - global_sender: &flume::Sender<GlobalBackGroundTaskMsg>, -) -> KvResult<BlockMetaV2> { - let block_for_cm = Arc::clone(&block); - let block_for_txs_mp = Arc::clone(&block); - - // Cm - crate::cm::update_current_meta(&block_for_cm, &global_sender); - - //TxsMp - let txs_mp_handle = dbs_pool - .launch(move |dbs| { - crate::txs_mp::apply_block(block_for_txs_mp.transactions(), &dbs.txs_mp_db)?; - Ok::<_, KvError>(()) - }) - .expect("dbs pool disconnected"); - - // Bc - let new_current = crate::bc::apply_block(bc_db, &block)?; - - txs_mp_handle.join().expect("dbs pool disconnected")?; - - Ok(new_current) -} - -fn apply_chunk_inner( - bc_db: &BcV2Db<FileBackend>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - blocks: Arc<[DubpBlockV10]>, - global_sender: Option<&flume::Sender<GlobalBackGroundTaskMsg>>, -) -> KvResult<BlockMetaV2> { - let blocks_len = blocks.len(); - let blocks_for_txs_mp = Arc::clone(&blocks); - - // Cm - if let Some(global_sender) = global_sender { - let chunk_len = blocks.len(); - crate::cm::update_current_meta(&&blocks.deref()[chunk_len - 1], &global_sender); - } - - //TxsMp - //log::info!("apply_chunk: launch txs_mp job..."); - let txs_mp_handle = dbs_pool - .launch(move |dbs| { - for block in blocks_for_txs_mp.deref() { - crate::txs_mp::apply_block(block.transactions(), &dbs.txs_mp_db)?; - } - Ok::<_, KvError>(()) - }) - .expect("apply_chunk_inner:txs_mp: dbs pool disconnected"); - - // Bc - //log::info!("apply_chunk: launch bc job..."); - for block in &blocks[..(blocks_len - 1)] { - crate::bc::apply_block(bc_db, block)?; - } - let current_block = crate::bc::apply_block(bc_db, &blocks[blocks_len - 1])?; - - txs_mp_handle - .join() - .expect("txs_mp_recv: dbs pool disconnected")?; - //log::info!("apply_chunk: txs_mp job finish."); - - Ok(current_block) -} diff --git a/rust-libs/duniter-dbs-write-ops/src/bc.rs b/rust-libs/duniter-dbs-write-ops/src/bc.rs deleted file mode 100644 index 17b2c1bc2..000000000 --- a/rust-libs/duniter-dbs-write-ops/src/bc.rs +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -mod identities; -mod txs; -mod uds; - -use crate::*; -use duniter_dbs::databases::bc_v2::BcV2DbWritable; - -pub fn apply_block<B: Backend>( - bc_db: &duniter_dbs::databases::bc_v2::BcV2Db<B>, - block: &DubpBlockV10, -) -> KvResult<BlockMetaV2> { - //log::info!("apply_block #{}", block.number().0); - let block_meta = BlockMetaV2::from(block); - - ( - bc_db.blocks_meta_write(), - bc_db.identities_write(), - bc_db.txs_hashs_write(), - bc_db.uds_write(), - bc_db.uds_reval_write(), - bc_db.uids_index_write(), - bc_db.utxos_write(), - bc_db.consumed_utxos_write(), - ) - .write( - |( - mut blocks_meta, - mut identities, - mut txs_hashs, - mut uds, - mut uds_reval, - mut uids_index, - mut utxos, - mut consumed_utxos, - )| { - blocks_meta.upsert(U32BE(block.number().0), block_meta); - identities::update_identities::<B>(&block, &mut identities)?; - for idty in block.identities() { - let pubkey = idty.issuers()[0]; - let username = idty.username().to_owned(); - uids_index.upsert(username, PubKeyValV2(pubkey)); - } - if let Some(dividend) = block.dividend() { - uds::create_uds::<B>( - block.number(), - dividend, - &mut identities, - &mut uds, - &mut uds_reval, - )?; - } - txs::apply_txs::<B>( - block.number(), - block.transactions(), - &mut txs_hashs, - &mut uds, - &mut utxos, - &mut consumed_utxos, - )?; - Ok(()) - }, - )?; - - if block_meta.number > ROLL_BACK_MAX { - prune_bc_db(bc_db, BlockNumber(block_meta.number))?; - } - - Ok(block_meta) -} - -fn prune_bc_db<B: Backend>( - bc_db: &duniter_dbs::databases::bc_v2::BcV2Db<B>, - current_block_number: BlockNumber, -) -> KvResult<()> { - bc_db - .consumed_utxos_write() - .remove(U32BE(current_block_number.0 - ROLL_BACK_MAX))?; - Ok(()) -} - -pub fn revert_block<B: Backend>( - bc_db: &duniter_dbs::databases::bc_v2::BcV2Db<B>, - block: &DubpBlockV10, -) -> KvResult<Option<BlockMetaV2>> { - ( - bc_db.blocks_meta_write(), - bc_db.identities_write(), - bc_db.txs_hashs_write(), - bc_db.uds_write(), - bc_db.uds_reval_write(), - bc_db.uids_index_write(), - bc_db.utxos_write(), - bc_db.consumed_utxos_write(), - ) - .write( - |( - mut blocks_meta, - mut identities, - mut txs_hashs, - mut uds, - mut uds_reval, - mut uids_index, - mut utxos, - mut consumed_utxos, - )| { - txs::revert_txs::<B>( - block.number(), - block.transactions(), - &mut txs_hashs, - &mut uds, - &mut utxos, - &mut consumed_utxos, - )?; - if block.dividend().is_some() { - uds::revert_uds::<B>( - block.number(), - &mut identities, - &mut uds, - &mut uds_reval, - )?; - } - identities::revert_identities::<B>(&block, &mut identities)?; - for idty in block.identities() { - let username = idty.username().to_owned(); - uids_index.remove(username); - } - blocks_meta.remove(U32BE(block.number().0)); - Ok(if block.number() == BlockNumber(0) { - None - } else { - blocks_meta.get(&U32BE(block.number().0 - 1))? - }) - }, - ) -} - -#[cfg(test)] -mod tests { - use super::*; - use dubp::{ - crypto::keys::{ed25519::PublicKey, PublicKey as _}, - documents::transaction::TransactionDocumentV10Stringified, - documents_parser::prelude::FromStringObject, - }; - use duniter_dbs::{ - databases::bc_v2::*, BlockUtxosV2Db, UtxoIdDbV2, WalletScriptWithSourceAmountV1Db, - }; - use maplit::hashmap; - - #[test] - fn test_bc_apply_block() -> anyhow::Result<()> { - let bc_db = BcV2Db::<Mem>::open(MemConf::default())?; - - let s1 = WalletScriptV10::single_sig(PublicKey::from_base58( - "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx", - )?); - let s2 = WalletScriptV10::single_sig(PublicKey::from_base58( - "4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m", - )?); - - let b0 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - version: 10, - median_time: 5_243, - dividend: Some(1000), - joiners: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&bc_db, &b0)?; - - assert_eq!(bc_db.blocks_meta().count()?, 1); - assert_eq!(bc_db.uds().count()?, 1); - assert_eq!(bc_db.utxos().count()?, 0); - assert_eq!(bc_db.consumed_utxos().count()?, 0); - - let b1 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - number: 1, - version: 10, - median_time: 5_245, - transactions: vec![TransactionDocumentV10Stringified { - currency: "test".to_owned(), - blockstamp: "0-0000000000000000000000000000000000000000000000000000000000000000".to_owned(), - locktime: 0, - issuers: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx".to_owned()], - inputs: vec!["1000:0:D:D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:0".to_owned()], - unlocks: vec![], - outputs: vec![ - "600:0:SIG(4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m)".to_owned(), - "400:0:SIG(D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx)".to_owned(), - ], - comment: "".to_owned(), - signatures: vec![], - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - }], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&bc_db, &b1)?; - - assert_eq!(bc_db.blocks_meta().count()?, 2); - assert_eq!(bc_db.uds().count()?, 0); - assert_eq!(bc_db.utxos().count()?, 2); - assert_eq!( - bc_db - .utxos() - .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, - vec![ - ( - UtxoIdDbV2(Hash::default(), 0), - WalletScriptWithSourceAmountV1Db { - wallet_script: s2.clone(), - source_amount: SourceAmount::with_base0(600) - } - ), - ( - UtxoIdDbV2(Hash::default(), 1), - WalletScriptWithSourceAmountV1Db { - wallet_script: s1.clone(), - source_amount: SourceAmount::with_base0(400) - } - ) - ] - ); - assert_eq!(bc_db.consumed_utxos().count()?, 0); - - let b2 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - number: 2, - version: 10, - median_time: 5_247, - transactions: vec![TransactionDocumentV10Stringified { - currency: "test".to_owned(), - blockstamp: "0-0000000000000000000000000000000000000000000000000000000000000000".to_owned(), - locktime: 0, - issuers: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx".to_owned()], - inputs: vec!["400:0:T:0000000000000000000000000000000000000000000000000000000000000000:1".to_owned()], - unlocks: vec![], - outputs: vec![ - "300:0:SIG(D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx)".to_owned(), - "100:0:SIG(4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m)".to_owned(), - ], - comment: "".to_owned(), - signatures: vec![], - hash: Some("0101010101010101010101010101010101010101010101010101010101010101".to_owned()), - }], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&bc_db, &b2)?; - - assert_eq!(bc_db.blocks_meta().count()?, 3); - assert_eq!(bc_db.uds().count()?, 0); - assert_eq!(bc_db.utxos().count()?, 3); - assert_eq!(bc_db.consumed_utxos().count()?, 1); - - assert_eq!( - bc_db - .consumed_utxos() - .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, - vec![( - U32BE(2), - BlockUtxosV2Db( - hashmap![UtxoIdV10 { tx_hash: Hash::default(), output_index: 1 } => WalletScriptWithSourceAmountV1Db { - wallet_script: s1.clone(), - source_amount: SourceAmount::with_base0(400) - }] - ) - )] - ); - - assert_eq!( - bc_db - .utxos() - .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, - vec![ - ( - UtxoIdDbV2(Hash::default(), 0), - WalletScriptWithSourceAmountV1Db { - wallet_script: s2.clone(), - source_amount: SourceAmount::with_base0(600) - } - ), - ( - UtxoIdDbV2(Hash([1; 32]), 0), - WalletScriptWithSourceAmountV1Db { - wallet_script: s1, - source_amount: SourceAmount::with_base0(300) - } - ), - ( - UtxoIdDbV2(Hash([1; 32]), 1), - WalletScriptWithSourceAmountV1Db { - wallet_script: s2, - source_amount: SourceAmount::with_base0(100) - } - ) - ] - ); - - Ok(()) - } -} diff --git a/rust-libs/duniter-dbs-write-ops/src/bc/identities.rs b/rust-libs/duniter-dbs-write-ops/src/bc/identities.rs deleted file mode 100644 index 024930874..000000000 --- a/rust-libs/duniter-dbs-write-ops/src/bc/identities.rs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use duniter_dbs::databases::bc_v2::IdentitiesEvent; -use duniter_dbs::IdtyDbV2; - -pub(crate) fn update_identities<B: Backend>( - block: &DubpBlockV10, - identities: &mut TxColRw<B::Col, IdentitiesEvent>, -) -> KvResult<()> { - for idty in block.identities() { - let pubkey = idty.issuers()[0]; - let username = idty.username().to_owned(); - identities.upsert( - PubKeyKeyV2(pubkey), - IdtyDbV2 { - is_member: true, - username, - }, - ) - } - for mb in block.joiners() { - let pubkey = mb.issuers()[0]; - let username = mb.identity_username().to_owned(); - identities.upsert( - PubKeyKeyV2(pubkey), - IdtyDbV2 { - is_member: true, - username, - }, - ) - } - for revo in block.revoked() { - let pubkey = revo.issuer; - if let Some(mut idty) = identities.get(&PubKeyKeyV2(pubkey))? { - idty.is_member = false; - identities.upsert(PubKeyKeyV2(pubkey), idty) - } - } - for pubkey in block.excluded().iter().copied() { - if let Some(mut idty) = identities.get(&PubKeyKeyV2(pubkey))? { - idty.is_member = false; - identities.upsert(PubKeyKeyV2(pubkey), idty) - } - } - Ok(()) -} - -pub(crate) fn revert_identities<B: Backend>( - block: &DubpBlockV10, - identities: &mut TxColRw<B::Col, IdentitiesEvent>, -) -> KvResult<()> { - for mb in block.joiners() { - let pubkey = mb.issuers()[0]; - let username = mb.identity_username().to_owned(); - identities.upsert( - PubKeyKeyV2(pubkey), - IdtyDbV2 { - is_member: false, - username, - }, - ) - } - for idty in block.identities() { - let pubkey = idty.issuers()[0]; - identities.remove(PubKeyKeyV2(pubkey)); - } - for revo in block.revoked() { - let pubkey = revo.issuer; - if let Some(mut idty) = identities.get(&PubKeyKeyV2(pubkey))? { - idty.is_member = true; - identities.upsert(PubKeyKeyV2(pubkey), idty) - } - } - for pubkey in block.excluded().iter().copied() { - if let Some(mut idty) = identities.get(&PubKeyKeyV2(pubkey))? { - idty.is_member = true; - identities.upsert(PubKeyKeyV2(pubkey), idty) - } - } - Ok(()) -} diff --git a/rust-libs/duniter-dbs-write-ops/src/bc/txs.rs b/rust-libs/duniter-dbs-write-ops/src/bc/txs.rs deleted file mode 100644 index d8154fd0c..000000000 --- a/rust-libs/duniter-dbs-write-ops/src/bc/txs.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use std::collections::HashMap; - -use crate::*; -use dubp::documents::transaction::TransactionOutputV10; -use duniter_dbs::{ - databases::bc_v2::{ConsumedUtxosEvent, TxsHashsEvent, UdsEvent, UtxosEvent}, - BlockUtxosV2Db, UdIdV2, UtxoIdDbV2, WalletScriptWithSourceAmountV1Db, -}; - -pub(crate) fn apply_txs<B: Backend>( - block_number: BlockNumber, - block_txs: &[TransactionDocumentV10], - txs_hashs: &mut TxColRw<B::Col, TxsHashsEvent>, - uds: &mut TxColRw<B::Col, UdsEvent>, - utxos: &mut TxColRw<B::Col, UtxosEvent>, - consumed_utxos: &mut TxColRw<B::Col, ConsumedUtxosEvent>, -) -> KvResult<()> { - if !block_txs.is_empty() { - let mut block_consumed_utxos = HashMap::with_capacity(block_txs.len() * 3); - for tx in block_txs { - let tx_hash = tx.get_hash(); - txs_hashs.upsert(HashKeyV2(tx_hash), ()); - for input in tx.get_inputs() { - match input.id { - SourceIdV10::Ud(UdSourceIdV10 { - issuer, - block_number, - }) => { - uds.remove(UdIdV2(issuer, block_number)); - } - SourceIdV10::Utxo(utxo_id) => { - let utxo_id_db = UtxoIdDbV2(utxo_id.tx_hash, utxo_id.output_index as u32); - if let Some(wallet_script_with_sa) = utxos.get(&utxo_id_db)? { - utxos.remove(utxo_id_db); - block_consumed_utxos.insert(utxo_id, wallet_script_with_sa); - } else { - return Err(KvError::Custom( - format!("db corrupted: not found utxo {:?}", utxo_id_db).into(), - )); - } - } - } - } - for (output_index, TransactionOutputV10 { amount, conditions }) in - tx.get_outputs().iter().enumerate() - { - let utxo_id = UtxoIdDbV2(tx_hash, output_index as u32); - let wallet_script_with_sa = WalletScriptWithSourceAmountV1Db { - wallet_script: conditions.script.clone(), - source_amount: *amount, - }; - utxos.upsert(utxo_id, wallet_script_with_sa); - } - } - if !block_consumed_utxos.is_empty() { - consumed_utxos.upsert(U32BE(block_number.0), BlockUtxosV2Db(block_consumed_utxos)); - } - } - Ok(()) -} - -pub(crate) fn revert_txs<B: Backend>( - block_number: BlockNumber, - block_txs: &[TransactionDocumentV10], - txs_hashs: &mut TxColRw<B::Col, TxsHashsEvent>, - uds: &mut TxColRw<B::Col, UdsEvent>, - utxos: &mut TxColRw<B::Col, UtxosEvent>, - consumed_utxos: &mut TxColRw<B::Col, ConsumedUtxosEvent>, -) -> KvResult<()> { - for tx in block_txs { - let tx_hash = tx.get_hash(); - txs_hashs.remove(HashKeyV2(tx_hash)); - for input in tx.get_inputs() { - match input.id { - SourceIdV10::Ud(UdSourceIdV10 { - issuer, - block_number, - }) => { - uds.upsert(UdIdV2(issuer, block_number), ()); - } - SourceIdV10::Utxo(utxo_id) => { - let utxo_id_db = UtxoIdDbV2(utxo_id.tx_hash, utxo_id.output_index as u32); - if let Some(block_utxos) = consumed_utxos.get(&U32BE(block_number.0))? { - if let Some(wallet_script_with_sa) = block_utxos.0.get(&utxo_id) { - utxos.upsert(utxo_id_db, wallet_script_with_sa.clone()); - } else { - return Err(KvError::Custom( - format!("db corrupted: not found consumed utxos {}", utxo_id) - .into(), - )); - } - } else { - return Err(KvError::Custom( - format!("db corrupted: not found consumed utxos {:?}", utxo_id_db) - .into(), - )); - } - } - } - if let SourceIdV10::Ud(UdSourceIdV10 { - issuer, - block_number, - }) = input.id - { - uds.upsert(UdIdV2(issuer, block_number), ()); - } - } - for output_index in 0..tx.get_outputs().len() { - let utxo_id = UtxoIdDbV2(tx_hash, output_index as u32); - utxos.remove(utxo_id); - } - } - consumed_utxos.remove(U32BE(block_number.0)); - Ok(()) -} diff --git a/rust-libs/duniter-dbs-write-ops/src/bc/uds.rs b/rust-libs/duniter-dbs-write-ops/src/bc/uds.rs deleted file mode 100644 index e8323f9bf..000000000 --- a/rust-libs/duniter-dbs-write-ops/src/bc/uds.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use duniter_dbs::{ - databases::bc_v2::{IdentitiesEvent, UdsEvent, UdsRevalEvent}, - UdIdV2, -}; - -pub(crate) fn create_uds<B: Backend>( - block_number: BlockNumber, - dividend: SourceAmount, - identities: &mut TxColRw<B::Col, IdentitiesEvent>, - uds: &mut TxColRw<B::Col, UdsEvent>, - uds_reval: &mut TxColRw<B::Col, UdsRevalEvent>, -) -> KvResult<()> { - let previous_ud_amount = uds_reval - .iter_rev(.., |it| it.values().next_res())? - .unwrap_or(SourceAmountValV2(SourceAmount::ZERO)); - if dividend > previous_ud_amount.0 { - uds_reval.upsert(U32BE(block_number.0), SourceAmountValV2(dividend)); - } - - let members = identities.iter(.., |it| { - it.filter_map_ok(|(pk, idty)| if idty.is_member { Some(pk.0) } else { None }) - .collect::<KvResult<Vec<_>>>() - })?; - for member in members { - uds.upsert(UdIdV2(member, block_number), ()); - } - Ok(()) -} - -pub(crate) fn revert_uds<B: Backend>( - block_number: BlockNumber, - identities: &mut TxColRw<B::Col, IdentitiesEvent>, - uds: &mut TxColRw<B::Col, UdsEvent>, - uds_reval: &mut TxColRw<B::Col, UdsRevalEvent>, -) -> KvResult<()> { - let previous_reval_block_number = uds_reval - .iter_rev(.., |it| it.keys().next_res())? - .expect("corrupted db") - .0; - if block_number.0 == previous_reval_block_number { - uds_reval.remove(U32BE(block_number.0)); - } - - let members = identities.iter(.., |it| { - it.filter_map_ok(|(pk, idty)| if idty.is_member { Some(pk.0) } else { None }) - .collect::<KvResult<Vec<_>>>() - })?; - for member in members { - uds.remove(UdIdV2(member, block_number)); - } - - Ok(()) -} diff --git a/rust-libs/duniter-dbs-write-ops/src/cm.rs b/rust-libs/duniter-dbs-write-ops/src/cm.rs deleted file mode 100644 index 5d9a61a27..000000000 --- a/rust-libs/duniter-dbs-write-ops/src/cm.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[inline(always)] -pub(crate) fn update_current_meta( - block: &DubpBlockV10, - global_sender: &flume::Sender<GlobalBackGroundTaskMsg>, -) { - let current_block_meta = block_to_block_meta(block); - global_sender - .send(GlobalBackGroundTaskMsg::NewCurrentBlock(current_block_meta)) - .expect("global task disconnected"); -} - -fn block_to_block_meta(block: &DubpBlockV10) -> BlockMetaV2 { - BlockMetaV2 { - version: 10, - number: block.number().0, - hash: block.hash().0, - signature: block.signature(), - inner_hash: block.inner_hash(), - previous_hash: block.previous_hash(), - issuer: block.issuer(), - previous_issuer: dubp::crypto::keys::ed25519::PublicKey::default(), - time: block.local_time(), - pow_min: block.pow_min() as u32, - members_count: block.members_count() as u64, - issuers_count: block.issuers_count() as u32, - issuers_frame: block.issuers_frame() as u64, - issuers_frame_var: 0, - median_time: block.common_time(), - nonce: block.nonce(), - monetary_mass: block.monetary_mass(), - unit_base: block.unit_base() as u32, - dividend: block.dividend(), - } -} diff --git a/rust-libs/duniter-dbs-write-ops/src/lib.rs b/rust-libs/duniter-dbs-write-ops/src/lib.rs deleted file mode 100644 index b112bce01..000000000 --- a/rust-libs/duniter-dbs-write-ops/src/lib.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -pub mod apply_block; -pub mod bc; -pub mod cm; -pub mod txs_mp; - -use std::borrow::Cow; - -use dubp::block::prelude::*; -use dubp::common::crypto::hashs::Hash; -use dubp::common::prelude::*; -use dubp::documents::{ - prelude::*, smallvec::SmallVec, transaction::TransactionDocumentTrait, - transaction::TransactionDocumentV10, -}; -use dubp::wallet::prelude::*; -use duniter_dbs::{ - databases::{ - bc_v2::BcV2Db, - txs_mp_v2::{TxsMpV2Db, TxsMpV2DbReadable, TxsMpV2DbWritable}, - }, - kv_typed::prelude::*, - BlockMetaV2, FileBackend, HashKeyV2, PendingTxDbV2, PubKeyKeyV2, PubKeyValV2, SharedDbs, - SourceAmountValV2, UtxoValV2, WalletConditionsV2, -}; -use duniter_global::GlobalBackGroundTaskMsg; -use resiter::filter_map::FilterMap; -use resiter::flatten::Flatten; -use resiter::map::Map; -use std::ops::Deref; - -const ROLL_BACK_MAX: u32 = 100; diff --git a/rust-libs/duniter-dbs-write-ops/src/txs_mp.rs b/rust-libs/duniter-dbs-write-ops/src/txs_mp.rs deleted file mode 100644 index 7f9e51395..000000000 --- a/rust-libs/duniter-dbs-write-ops/src/txs_mp.rs +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub fn apply_block<B: Backend>( - block_txs: &[TransactionDocumentV10], - txs_mp_db: &TxsMpV2Db<B>, -) -> KvResult<()> { - for tx in block_txs { - // Remove tx from mempool - remove_one_pending_tx(&txs_mp_db, tx.get_hash())?; - } - Ok(()) -} - -pub fn revert_block<B: Backend>( - block_txs: &[TransactionDocumentV10], - txs_mp_db: &TxsMpV2Db<B>, -) -> KvResult<()> { - for tx in block_txs { - // Rewrite tx on mempool - add_pending_tx(|_, _| Ok(()), txs_mp_db, Cow::Borrowed(tx))?; - } - Ok(()) -} - -pub fn add_pending_tx< - B: Backend, - F: FnOnce( - &TransactionDocumentV10, - &TxColRw<B::Col, duniter_dbs::databases::txs_mp_v2::TxsEvent>, - ) -> KvResult<()>, ->( - control: F, - txs_mp_db: &TxsMpV2Db<B>, - tx: Cow<TransactionDocumentV10>, -) -> KvResult<()> { - let tx_hash = tx.get_hash(); - let received_time = chrono::offset::Utc::now().timestamp(); - ( - txs_mp_db.txs_by_recv_time_write(), - txs_mp_db.txs_by_issuer_write(), - txs_mp_db.txs_by_recipient_write(), - txs_mp_db.txs_write(), - txs_mp_db.uds_ids_write(), - txs_mp_db.utxos_ids_write(), - txs_mp_db.outputs_by_script_write(), - ) - .write( - |( - mut txs_by_recv_time, - mut txs_by_issuer, - mut txs_by_recipient, - mut txs, - mut uds_ids, - mut utxos_ids, - mut outputs_by_script, - )| { - control(&tx, &txs)?; - // Insert on col `txs_by_recv_time` - let mut hashs = txs_by_recv_time.get(&received_time)?.unwrap_or_default(); - hashs.insert(tx_hash); - txs_by_recv_time.upsert(received_time, hashs); - // Insert on col `txs_by_issuer` - for pubkey in tx.issuers() { - let mut hashs = txs_by_issuer.get(&PubKeyKeyV2(pubkey))?.unwrap_or_default(); - hashs.insert(tx.get_hash()); - txs_by_issuer.upsert(PubKeyKeyV2(pubkey), hashs); - } - // Insert on col `txs_by_recipient` - for pubkey in tx.recipients_keys() { - let mut hashs = txs_by_recipient - .get(&PubKeyKeyV2(pubkey))? - .unwrap_or_default(); - hashs.insert(tx.get_hash()); - txs_by_recipient.upsert(PubKeyKeyV2(pubkey), hashs); - } - // Insert tx inputs in cols `uds_ids` and `utxos_ids` - for input in tx.get_inputs() { - match input.id { - SourceIdV10::Ud(UdSourceIdV10 { - issuer, - block_number, - }) => uds_ids.upsert(duniter_dbs::UdIdV2(issuer, block_number), ()), - SourceIdV10::Utxo(UtxoIdV10 { - tx_hash, - output_index, - }) => utxos_ids - .upsert(duniter_dbs::UtxoIdDbV2(tx_hash, output_index as u32), ()), - } - } - // Insert tx outputs in col `outputs` - for (output_index, output) in tx.get_outputs().iter().enumerate() { - let script = WalletConditionsV2(output.conditions.script.to_owned()); - let utxo = UtxoValV2::new(output.amount, tx_hash, output_index as u32); - let mut script_outputs = outputs_by_script.get(&script)?.unwrap_or_default(); - script_outputs.insert(utxo); - outputs_by_script.upsert(script, script_outputs); - } - // Insert tx itself - txs.upsert(HashKeyV2(tx_hash), PendingTxDbV2(tx.into_owned())); - Ok(()) - }, - ) -} - -pub fn remove_all_pending_txs<B: Backend>(txs_mp_db: &TxsMpV2Db<B>) -> KvResult<()> { - txs_mp_db.txs_by_recv_time_write().clear()?; - txs_mp_db.txs_by_issuer_write().clear()?; - txs_mp_db.txs_by_recipient_write().clear()?; - txs_mp_db.txs_write().clear()?; - txs_mp_db.uds_ids_write().clear()?; - txs_mp_db.utxos_ids_write().clear()?; - - Ok(()) -} - -pub fn remove_pending_tx_by_hash<B: Backend>(txs_mp_db: &TxsMpV2Db<B>, hash: Hash) -> KvResult<()> { - remove_one_pending_tx(&txs_mp_db, hash)?; - Ok(()) -} - -pub fn trim_expired_non_written_txs<B: Backend>( - txs_mp_db: &TxsMpV2Db<B>, - limit_time: i64, -) -> KvResult<()> { - // Get hashs of tx to remove and "times" to remove - let mut times = Vec::new(); - let hashs = txs_mp_db.txs_by_recv_time().iter(..limit_time, |it| { - it.map_ok(|(k, v)| { - times.push(k); - v - }) - .flatten_ok() - .collect::<KvResult<SmallVec<[Hash; 4]>>>() - })?; - // For each tx to remove - for (hash, time) in hashs.into_iter().zip(times.into_iter()) { - remove_one_pending_tx(&txs_mp_db, hash)?; - // Remove txs hashs in col `txs_by_recv_time` - txs_mp_db.txs_by_recv_time_write().remove(time)?; - } - - Ok(()) -} - -fn remove_one_pending_tx<B: Backend>(txs_mp_db: &TxsMpV2Db<B>, tx_hash: Hash) -> KvResult<bool> { - if let Some(tx) = txs_mp_db.txs().get(&HashKeyV2(tx_hash))? { - ( - txs_mp_db.txs_by_issuer_write(), - txs_mp_db.txs_by_recipient_write(), - txs_mp_db.txs_write(), - txs_mp_db.uds_ids_write(), - txs_mp_db.utxos_ids_write(), - txs_mp_db.outputs_by_script_write(), - ) - .write( - |( - mut txs_by_issuer, - mut txs_by_recipient, - mut txs, - mut uds_ids, - mut utxos_ids, - mut outputs_by_script, - )| { - // Remove tx inputs in cols `uds_ids` and `utxos_ids` - for input in tx.0.get_inputs() { - match input.id { - SourceIdV10::Ud(UdSourceIdV10 { - issuer, - block_number, - }) => uds_ids.remove(duniter_dbs::UdIdV2(issuer, block_number)), - SourceIdV10::Utxo(UtxoIdV10 { - tx_hash, - output_index, - }) => utxos_ids - .remove(duniter_dbs::UtxoIdDbV2(tx_hash, output_index as u32)), - } - } - // Remove tx hash in col `txs_by_issuer` - for pubkey in tx.0.issuers() { - let mut hashs_ = - txs_by_issuer.get(&PubKeyKeyV2(pubkey))?.unwrap_or_default(); - hashs_.remove(&tx_hash); - txs_by_issuer.upsert(PubKeyKeyV2(pubkey), hashs_) - } - // Remove tx hash in col `txs_by_recipient` - for pubkey in tx.0.recipients_keys() { - let mut hashs_ = txs_by_recipient - .get(&PubKeyKeyV2(pubkey))? - .unwrap_or_default(); - hashs_.remove(&tx_hash); - txs_by_recipient.upsert(PubKeyKeyV2(pubkey), hashs_) - } - // Remove tx outputs in col `outputs` - for (output_index, output) in tx.0.get_outputs().iter().enumerate() { - let script = WalletConditionsV2(output.conditions.script.to_owned()); - let utxo = UtxoValV2::new(output.amount, tx_hash, output_index as u32); - let mut script_outputs = - outputs_by_script.get(&script)?.unwrap_or_default(); - script_outputs.remove(&utxo); - outputs_by_script.upsert(script, script_outputs); - } - // Remove tx itself - txs.remove(HashKeyV2(tx_hash)); - Ok(true) - }, - ) - } else { - Ok(false) - } -} diff --git a/rust-libs/duniter-dbs/Cargo.toml b/rust-libs/duniter-dbs/Cargo.toml deleted file mode 100644 index 85437e4e2..000000000 --- a/rust-libs/duniter-dbs/Cargo.toml +++ /dev/null @@ -1,48 +0,0 @@ -[package] -name = "duniter-dbs" -version = "0.1.0" -authors = ["elois <elois@duniter.org>"] -description = "Duniter blockchain DB" -repository = "https://git.duniter.org/nodes/typescript/duniter" -keywords = ["dubp", "duniter", "blockchain", "database"] -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -arrayvec = "0.5.1" -bincode = "1.2.1" -byteorder = "1.3.4" -chrono = { version = "0.4.15", optional = true } -dubp = { version = "0.51.0", features = ["duniter"] } -kv_typed = { path = "../tools/kv_typed", default-features = false } -log = "0.4.8" -mockall = { version = "0.9.1", optional = true } -parking_lot = "0.11.0" -paste = "1.0.2" -rand = "0.7.3" -serde = { version = "1.0.105", features = ["derive"] } -serde_json = "1.0.53" -smallvec = { version = "1.4.0", features = ["serde", "write"] } -thiserror = "1.0.20" -uninit = "0.4.0" -zerocopy = "0.3.0" - -[dev-dependencies] -anyhow = "1.0.34" -tempfile = "3.2.0" -unwrap = "1.2.1" - -[features] -default = ["sled_backend"] - -# CAUTION: feature "leveldb_backend" MUST BE DISABLED by default. Uncomment this line for dev/test only ! -#default = ["sled_backend", "explorer", "leveldb_backend"] - -explorer = ["chrono", "kv_typed/explorer"] -leveldb_backend = ["kv_typed/leveldb_backend"] -mem = [] -#mock = ["kv_typed/mock", "mockall"] -sled_backend = ["kv_typed/sled_backend"] diff --git a/rust-libs/duniter-dbs/src/databases.rs b/rust-libs/duniter-dbs/src/databases.rs deleted file mode 100644 index 19792fc7c..000000000 --- a/rust-libs/duniter-dbs/src/databases.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -pub mod bc_v1; -pub mod bc_v2; -pub mod cm_v1; -pub mod network_v1; -pub mod txs_mp_v2; diff --git a/rust-libs/duniter-dbs/src/databases/bc_v1.rs b/rust-libs/duniter-dbs/src/databases/bc_v1.rs deleted file mode 100644 index bf01ede5e..000000000 --- a/rust-libs/duniter-dbs/src/databases/bc_v1.rs +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -db_schema!( - BcV1, - [ - ["level_blockchain", MainBlocks, BlockNumberKeyV1, BlockDbV1], - [ - "level_blockchain/idty", - MbIdty, - PubKeyKeyV1, - BlockNumberArrayV1 - ], - [ - "level_blockchain/certs", - MbCerts, - PubKeyKeyV1, - BlockNumberArrayV1 - ], - [ - "level_blockchain/joiners", - MbJoiners, - PubKeyKeyV1, - BlockNumberArrayV1 - ], - [ - "level_blockchain/actives", - MbActives, - PubKeyKeyV1, - BlockNumberArrayV1 - ], - [ - "level_blockchain/leavers", - MbLeavers, - PubKeyKeyV1, - BlockNumberArrayV1 - ], - [ - "level_blockchain/excluded", - MbExcluded, - PubKeyKeyV1, - BlockNumberArrayV1 - ], - [ - "level_blockchain/revoked", - MbRevoked, - PubKeyAndSigV1, - BlockNumberArrayV1 - ], - [ - "level_blockchain/dividends", - MbDividends, - AllKeyV1, - BlockNumberArrayV1 - ], - [ - "level_blockchain/transactions", - MbTransactions, - AllKeyV1, - BlockNumberArrayV1 - ], - [ - "level_blockchain/forks", - ForkBlocks, - BlockstampKeyV1, - BlockDbV1 - ], - ["level_bindex", Bindex, BlockNumberKeyV1, BlockHeadDbV1], - ["level_iindex", Iindex, PubKeyKeyV1, IIndexDbV1], - [ - "level_iindex/hash", - IindexHash, - HashKeyV1, - PublicKeySingletonDbV1 - ], - ["level_iindex/kick", IindexKick, PubKeyKeyV1, KickDbV1], - [ - "level_iindex/writtenOn", - IindexWrittenOn, - BlockNumberKeyV1, - PublicKeyArrayDbV1 - ], - ["level_iindex/uid", Uids, UidKeyV1, PublicKeySingletonDbV1], - ["level_mindex", Mindex, PubKeyKeyV1, MIndexDbV1], - [ - "level_mindex/expiresOn", - MindexExpiresOn, - TimestampKeyV1, - PublicKeyArrayDbV1 - ], - [ - "level_mindex/revokesOn", - MindexRevokesOn, - TimestampKeyV1, - PublicKeyArrayDbV1 - ], - [ - "level_mindex/writtenOn", - MindexWrittenOn, - BlockNumberKeyV1, - PublicKeyArrayDbV1 - ], - ["level_cindex", Cindex, PubKeyKeyV1, CIndexDbV1], - [ - "level_cindex/expiresOn", - CindexExpiresOn, - BlockNumberKeyV1, - PublicKeyArrayDbV1 - ], - [ - "level_cindex/writtenOn", - CindexWrittenOn, - BlockNumberKeyV1, - PublicKeyArrayDbV1 - ], - ["level_wallet", Wallet, WalletConditionsV1, WalletDbV1], - ["level_dividend", Uds, PubKeyKeyV1, UdEntryDbV1], - [ - "level_dividend/level_dividend_trim_index", - UdsTrim, - BlockNumberKeyV1, - PublicKeyArrayDbV1 - ], - ["level_sindex", Sindex, SourceKeyV1, SIndexDBV1], - [ - "level_sindex/written_on", - SindexWrittenOn, - BlockNumberKeyV1, - SourceKeyArrayDbV1 - ], - [ - "level_sindex/consumed_on", - SindexConsumedOn, - BlockNumberKeyV1, - SourceKeyArrayDbV1 - ], - [ - "level_sindex/conditions", - SindexConditions, - WalletConditionsV1, - SourceKeyArrayDbV1 - ], - ] -); diff --git a/rust-libs/duniter-dbs/src/databases/bc_v2.rs b/rust-libs/duniter-dbs/src/databases/bc_v2.rs deleted file mode 100644 index c52560296..000000000 --- a/rust-libs/duniter-dbs/src/databases/bc_v2.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -db_schema!( - BcV2, - [ - ["blocks_meta", BlocksMeta, U32BE, BlockMetaV2], - ["identities", Identities, PubKeyKeyV2, IdtyDbV2], - ["txs_hashs", TxsHashs, HashKeyV2, ()], - ["uds", Uds, UdIdV2, ()], - ["uds_reval", UdsReval, U32BE, SourceAmountValV2], - ["uids_index", UidsIndex, String, PubKeyValV2], - ["utxos", Utxos, UtxoIdDbV2, WalletScriptWithSourceAmountV1Db], - ["consumed_utxos", ConsumedUtxos, U32BE, BlockUtxosV2Db], - ] -); diff --git a/rust-libs/duniter-dbs/src/databases/cm_v1.rs b/rust-libs/duniter-dbs/src/databases/cm_v1.rs deleted file mode 100644 index 4cea86827..000000000 --- a/rust-libs/duniter-dbs/src/databases/cm_v1.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -db_schema!(CmV1, [["current_block", CurrentBlock, (), BlockDbV2],]); diff --git a/rust-libs/duniter-dbs/src/databases/network_v1.rs b/rust-libs/duniter-dbs/src/databases/network_v1.rs deleted file mode 100644 index db55149ae..000000000 --- a/rust-libs/duniter-dbs/src/databases/network_v1.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -db_schema!( - NetworkV1, - [ - ["heads_old", HeadsOld, DunpNodeIdV1Db, DunpHeadDbV1], - ["peers_old", PeersOld, PubKeyKeyV2, PeerCardDbV1], - ] -); diff --git a/rust-libs/duniter-dbs/src/databases/txs_mp_v2.rs b/rust-libs/duniter-dbs/src/databases/txs_mp_v2.rs deleted file mode 100644 index e05532807..000000000 --- a/rust-libs/duniter-dbs/src/databases/txs_mp_v2.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -db_schema!( - TxsMpV2, - [ - ["txs", Txs, HashKeyV2, PendingTxDbV2], - ["txs_by_issuer", TxsByIssuer, PubKeyKeyV2, BTreeSet<Hash>], - ["txs_by_recipient", TxsByRecipient, PubKeyKeyV2, BTreeSet<Hash>], - ["txs_by_received_time", TxsByRecvTime, i64, BTreeSet<Hash>], - ["uds_ids", UdsIds, UdIdV2, ()], - ["utxos_ids", UtxosIds, UtxoIdDbV2, ()], - ["outputs_by_script", OutputsByScript, WalletConditionsV2, BTreeSet<UtxoValV2>], - ] -); diff --git a/rust-libs/duniter-dbs/src/keys.rs b/rust-libs/duniter-dbs/src/keys.rs deleted file mode 100644 index b5d2db16b..000000000 --- a/rust-libs/duniter-dbs/src/keys.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -pub mod all; -pub mod block_number; -pub mod blockstamp; -pub mod dunp_node_id; -pub mod hash; -pub mod pubkey; -pub mod pubkey_and_sig; -pub mod source_key; -pub mod timestamp; -pub mod ud_id; -pub mod uid; -pub mod utxo_id; -pub mod wallet_conditions; diff --git a/rust-libs/duniter-dbs/src/keys/all.rs b/rust-libs/duniter-dbs/src/keys/all.rs deleted file mode 100644 index 3515a52f5..000000000 --- a/rust-libs/duniter-dbs/src/keys/all.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct AllKeyV1; - -impl AsBytes for AllKeyV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(b"ALL") - } -} - -impl kv_typed::prelude::FromBytes for AllKeyV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - if bytes == b"ALL" { - Ok(Self) - } else { - Err(CorruptedBytes(format!( - "Invalid key: expected '{:?}', found '{:?}'", - b"ALL", bytes - ))) - } - } -} - -impl ToDumpString for AllKeyV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for AllKeyV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - <Self as kv_typed::prelude::FromBytes>::from_bytes(source.as_bytes()) - .map_err(|e| FromExplorerKeyErr(e.0.into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - self.as_bytes(|bytes| Ok(unsafe { std::str::from_utf8_unchecked(bytes) }.to_owned())) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/block_number.rs b/rust-libs/duniter-dbs/src/keys/block_number.rs deleted file mode 100644 index afd226849..000000000 --- a/rust-libs/duniter-dbs/src/keys/block_number.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct BlockNumberKeyV1(pub BlockNumber); - -impl AsBytes for BlockNumberKeyV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - if self.0 == BlockNumber(u32::MAX) { - f(b"0000000NaN") - } else { - f(format!("{:010}", (self.0).0).as_bytes()) - } - } -} - -impl FromBytes for BlockNumberKeyV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let key_str = std::str::from_utf8(bytes).map_err(|e| CorruptedBytes(e.to_string()))?; - if key_str == "0000000NaN" { - Ok(BlockNumberKeyV1(BlockNumber(u32::MAX))) - } else { - Ok(BlockNumberKeyV1(BlockNumber(key_str.parse().map_err( - |e| CorruptedBytes(format!("{}: {}", e, key_str)), - )?))) - } - } -} - -impl ToDumpString for BlockNumberKeyV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for BlockNumberKeyV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerKeyErr(e.0.into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(format!("{}", (self.0).0)) - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn test_block_number_str_10_ser() { - BlockNumberKeyV1(BlockNumber(35)) - .as_bytes(|bytes| assert_eq!(bytes, &[48, 48, 48, 48, 48, 48, 48, 48, 51, 53])) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/blockstamp.rs b/rust-libs/duniter-dbs/src/keys/blockstamp.rs deleted file mode 100644 index 6b4a8df39..000000000 --- a/rust-libs/duniter-dbs/src/keys/blockstamp.rs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct BlockstampKeyV1(Blockstamp); - -impl AsBytes for BlockstampKeyV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(format!("{:010}-{}", self.0.number.0, self.0.hash).as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for BlockstampKeyV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let blockstamp_strs: ArrayVec<[&str; 2]> = std::str::from_utf8(bytes) - .map_err(|e| CorruptedBytes(e.to_string()))? - .split('-') - .collect(); - let block_number = blockstamp_strs[0] - .parse() - .map_err(|e: ParseIntError| CorruptedBytes(e.to_string()))?; - let block_hash = - Hash::from_hex(blockstamp_strs[1]).map_err(|e| CorruptedBytes(e.to_string()))?; - Ok(BlockstampKeyV1(Blockstamp { - number: BlockNumber(block_number), - hash: BlockHash(block_hash), - })) - } -} - -impl ToDumpString for BlockstampKeyV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for BlockstampKeyV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerKeyErr(e.0.into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(format!("{}", self.0)) - } -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct BlockstampKeyV2(Blockstamp); - -impl AsBytes for BlockstampKeyV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let bytes: [u8; 36] = self.0.into(); - f(&bytes[..]) - } -} - -impl kv_typed::prelude::FromBytes for BlockstampKeyV2 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - use dubp::common::bytes_traits::FromBytes as _; - Ok(Self( - Blockstamp::from_bytes(bytes).map_err(|e| CorruptedBytes(e.to_string()))?, - )) - } -} - -impl ToDumpString for BlockstampKeyV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for BlockstampKeyV2 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Ok(Self( - Blockstamp::from_str(source).map_err(|e| FromExplorerKeyErr(e.into()))?, - )) - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(format!("{}", self.0)) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/dunp_node_id.rs b/rust-libs/duniter-dbs/src/keys/dunp_node_id.rs deleted file mode 100644 index 31e232d41..000000000 --- a/rust-libs/duniter-dbs/src/keys/dunp_node_id.rs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use std::fmt::Display; -use uninit::prelude::*; - -#[derive( - Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, zerocopy::AsBytes, zerocopy::FromBytes, -)] -#[repr(transparent)] -pub struct DunpNodeIdV1Db([u8; 37]); // uuid ++ pubkey - -impl DunpNodeIdV1Db { - pub fn new(uuid: u32, pubkey: PublicKey) -> Self { - let mut buffer = uninit_array![u8; 37]; - let (pubkey_buffer, uuid_buffer) = buffer.as_out().split_at_out(33); - - pubkey_buffer.copy_from_slice(pubkey.as_ref()); - uuid_buffer.copy_from_slice(&uuid.to_be_bytes()[..]); - - Self(unsafe { std::mem::transmute(buffer) }) - } - pub fn get_uuid(&self) -> u32 { - let mut buffer = uninit_array![u8; 4]; - - buffer.as_out().copy_from_slice(&self.0[33..]); - - u32::from_be_bytes(unsafe { std::mem::transmute(buffer) }) - } - pub fn get_pubkey(&self) -> PublicKey { - let mut buffer = uninit_array![u8; 33]; - - buffer.as_out().copy_from_slice(&self.0[..33]); - let bytes: [u8; 33] = unsafe { std::mem::transmute(buffer) }; - - PublicKey::try_from(&bytes[..]).unwrap_or_else(|_| unreachable!()) - } -} - -impl Default for DunpNodeIdV1Db { - fn default() -> Self { - DunpNodeIdV1Db([0u8; 37]) - } -} - -impl Display for DunpNodeIdV1Db { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:x}-{}", self.get_uuid(), self.get_pubkey()) - } -} - -impl AsBytes for DunpNodeIdV1Db { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.0.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for DunpNodeIdV1Db { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let layout = zerocopy::LayoutVerified::<_, DunpNodeIdV1Db>::new(bytes) - .ok_or_else(|| CorruptedBytes("corrupted db".to_owned()))?; - Ok(*layout) - } -} - -impl ToDumpString for DunpNodeIdV1Db { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for DunpNodeIdV1Db { - fn from_explorer_str(_: &str) -> std::result::Result<Self, FromExplorerKeyErr> { - unimplemented!() - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(self.to_string()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_serde() { - let node_id = DunpNodeIdV1Db::new(42, PublicKey::default()); - assert_eq!(node_id.get_uuid(), 42); - assert_eq!(node_id.get_pubkey(), PublicKey::default()); - let mut node_id_ = DunpNodeIdV1Db([0u8; 37]); - node_id_.0[32] = 32; - node_id_.0[36] = 42; - assert_eq!(node_id_, node_id) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/hash.rs b/rust-libs/duniter-dbs/src/keys/hash.rs deleted file mode 100644 index c223810c7..000000000 --- a/rust-libs/duniter-dbs/src/keys/hash.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct HashKeyV1(pub Hash); - -impl AsBytes for HashKeyV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.0.to_hex().as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for HashKeyV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let hash_str = std::str::from_utf8(bytes).map_err(|e| CorruptedBytes(e.to_string()))?; - Ok(HashKeyV1( - Hash::from_hex(&hash_str).map_err(|e| CorruptedBytes(e.to_string()))?, - )) - } -} - -impl ToDumpString for HashKeyV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for HashKeyV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerKeyErr(e.0.into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - self.as_bytes(|bytes| Ok(unsafe { std::str::from_utf8_unchecked(bytes) }.to_owned())) - } -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -#[repr(transparent)] -pub struct HashKeyV2(pub Hash); - -impl HashKeyV2 { - pub fn from_ref(hash: &Hash) -> &Self { - #[allow(trivial_casts)] - unsafe { - &*(hash as *const Hash as *const HashKeyV2) - } - } -} - -impl AsBytes for HashKeyV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.0.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for HashKeyV2 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - if bytes.len() != 32 { - Err(CorruptedBytes(format!( - "Invalid length: expected 32 found {}", - bytes.len() - ))) - } else { - let mut buffer = [0u8; 32]; - buffer.copy_from_slice(bytes); - Ok(HashKeyV2(Hash(buffer))) - } - } -} - -impl ToDumpString for HashKeyV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for HashKeyV2 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Ok(Self( - Hash::from_hex(source).map_err(|e| FromExplorerKeyErr(e.into()))?, - )) - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(self.0.to_hex()) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/pubkey.rs b/rust-libs/duniter-dbs/src/keys/pubkey.rs deleted file mode 100644 index 7441f5130..000000000 --- a/rust-libs/duniter-dbs/src/keys/pubkey.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct PubKeyKeyV1(pub PublicKey); - -impl PubKeyKeyV1 { - const ALL: &'static str = "ALL"; - const ALL_WITH_LEADING_1: &'static str = "11111111111111111111111111111ALL"; - - pub fn all() -> Self { - Self(PublicKey::from_base58(Self::ALL).expect("invalid PubKeyKeyV1::all()")) - } -} - -impl AsBytes for PubKeyKeyV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let b58_string = self.0.to_base58(); - if b58_string == Self::ALL_WITH_LEADING_1 { - f(Self::ALL.as_bytes()) - } else { - f(self.0.to_base58().as_bytes()) - } - } -} - -impl kv_typed::prelude::FromBytes for PubKeyKeyV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let pubkey_str = std::str::from_utf8(bytes).map_err(|e| CorruptedBytes(e.to_string()))?; - Ok(PubKeyKeyV1(PublicKey::from_base58(&pubkey_str).map_err( - |e| CorruptedBytes(format!("{}: {}", e, pubkey_str)), - )?)) - } -} - -impl ToDumpString for PubKeyKeyV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct PubKeyKeyV2(pub PublicKey); - -impl AsBytes for PubKeyKeyV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.0.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for PubKeyKeyV2 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - Ok(PubKeyKeyV2(PublicKey::try_from(bytes).map_err(|e| { - CorruptedBytes(format!("{}: {:?}", e, bytes)) - })?)) - } -} - -impl ToDumpString for PubKeyKeyV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for PubKeyKeyV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerKeyErr(e.0.into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - self.as_bytes(|bytes| Ok(unsafe { std::str::from_utf8_unchecked(bytes) }.to_owned())) - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for PubKeyKeyV2 { - fn from_explorer_str(pubkey_str: &str) -> std::result::Result<Self, FromExplorerKeyErr> { - Ok(PubKeyKeyV2(PublicKey::from_base58(&pubkey_str).map_err( - |e| FromExplorerKeyErr(format!("{}: {}", e, pubkey_str).into()), - )?)) - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(self.0.to_base58()) - } -} - -#[cfg(test)] -mod tests { - - use super::*; - #[test] - fn pubkey_all() { - let all = PubKeyKeyV1::all(); - assert_eq!( - all.as_bytes(|bytes| bytes.to_vec()), - PubKeyKeyV1::ALL.as_bytes() - ) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/pubkey_and_sig.rs b/rust-libs/duniter-dbs/src/keys/pubkey_and_sig.rs deleted file mode 100644 index 47a14c90c..000000000 --- a/rust-libs/duniter-dbs/src/keys/pubkey_and_sig.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct PubKeyAndSigV1(PublicKey, Signature); - -impl PubKeyAndSigV1 { - pub fn all() -> Self { - Self(PublicKey::default(), Signature([0u8; 64])) - } -} - -impl AsBytes for PubKeyAndSigV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - if self == &Self::all() { - f(b"ALL") - } else { - f(format!("{}:{}", self.0.to_base58(), self.1.to_base64()).as_bytes()) - } - } -} - -impl kv_typed::prelude::FromBytes for PubKeyAndSigV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let raw_str = std::str::from_utf8(bytes).map_err(|e| CorruptedBytes(e.to_string()))?; - if raw_str == "ALL" { - Ok(PubKeyAndSigV1::all()) - } else { - let array_str: ArrayVec<[&str; 2]> = raw_str.split(':').collect(); - let pubkey = - PublicKey::from_base58(array_str[0]).map_err(|e| CorruptedBytes(e.to_string()))?; - let sig = - Signature::from_base64(array_str[1]).map_err(|e| CorruptedBytes(e.to_string()))?; - Ok(PubKeyAndSigV1(pubkey, sig)) - } - } -} - -impl ToDumpString for PubKeyAndSigV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for PubKeyAndSigV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerKeyErr(e.0.into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - self.as_bytes(|bytes| Ok(unsafe { std::str::from_utf8_unchecked(bytes) }.to_owned())) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/source_key.rs b/rust-libs/duniter-dbs/src/keys/source_key.rs deleted file mode 100644 index accb5c9a9..000000000 --- a/rust-libs/duniter-dbs/src/keys/source_key.rs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Serialize)] -pub struct SourceKeyV1 { - pub tx_hash: Hash, - pub pos: u32, - pub consumed: Option<bool>, -} - -impl ToString for SourceKeyV1 { - fn to_string(&self) -> String { - format!( - "{}-{:010}{}", - self.tx_hash, - self.pos, - match self.consumed { - Some(true) => "-1", - Some(false) => "-0", - None => "", - } - ) - } -} - -impl AsBytes for SourceKeyV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.to_string().as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for SourceKeyV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let strs: ArrayVec<[&str; 3]> = std::str::from_utf8(bytes) - .map_err(|e| CorruptedBytes(e.to_string()))? - .split('-') - .collect(); - let tx_hash = Hash::from_hex(strs[0]).map_err(|e| CorruptedBytes(e.to_string()))?; - let pos = strs[1] - .parse() - .map_err(|e: ParseIntError| CorruptedBytes(e.to_string()))?; - let consumed = if strs.len() <= 2 { - None - } else { - match strs[2] { - "1" => Some(true), - "0" => Some(false), - _ => { - return Err(CorruptedBytes( - "invalid format: field consumed must be encoded with '0' or '1'".to_owned(), - )) - } - } - }; - Ok(SourceKeyV1 { - tx_hash, - pos, - consumed, - }) - } -} - -impl ToDumpString for SourceKeyV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for SourceKeyV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerKeyErr(e.0.into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - self.as_bytes(|bytes| Ok(unsafe { std::str::from_utf8_unchecked(bytes) }.to_owned())) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/timestamp.rs b/rust-libs/duniter-dbs/src/keys/timestamp.rs deleted file mode 100644 index 96a6cb8ce..000000000 --- a/rust-libs/duniter-dbs/src/keys/timestamp.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct TimestampKeyV1(pub u64); - -impl AsBytes for TimestampKeyV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(format!("{}", self.0).as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for TimestampKeyV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let key_str = std::str::from_utf8(bytes).map_err(|e| CorruptedBytes(e.to_string()))?; - Ok(TimestampKeyV1(key_str.parse().map_err(|e| { - CorruptedBytes(format!("{}: {}", e, key_str)) - })?)) - } -} - -impl ToDumpString for TimestampKeyV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for TimestampKeyV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - NaiveDateTime::parse_from_str(source, "%Y-%m-%d %H:%M:%S") - .map(|dt| TimestampKeyV1(dt.timestamp() as u64)) - .map_err(|e| FromExplorerKeyErr(format!("{}: {}", e, source).into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(NaiveDateTime::from_timestamp(self.0 as i64, 0) - .format("%Y-%m-%d %H:%M:%S") - .to_string()) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/ud_id.rs b/rust-libs/duniter-dbs/src/keys/ud_id.rs deleted file mode 100644 index a1e3b24ce..000000000 --- a/rust-libs/duniter-dbs/src/keys/ud_id.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use uninit::prelude::*; - -#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] -pub struct UdIdV2(pub PublicKey, pub BlockNumber); - -impl PartialOrd for UdIdV2 { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - match self.0.partial_cmp(&other.0) { - Some(std::cmp::Ordering::Equal) => self.1.partial_cmp(&other.1), - o => o, - } - } -} -impl Ord for UdIdV2 { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - match self.0.cmp(&other.0) { - std::cmp::Ordering::Equal => self.1.cmp(&other.1), - o => o, - } - } -} - -impl AsBytes for UdIdV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let mut buffer = uninit_array![u8; 37]; - let (pubkey_buffer, block_number_buffer) = buffer.as_out().split_at_out(33); - let pubkey_buffer = pubkey_buffer.copy_from_slice(self.0.as_ref()); - block_number_buffer.copy_from_slice(&(self.1).0.to_be_bytes()); - f(unsafe { std::slice::from_raw_parts_mut(pubkey_buffer.as_mut_ptr(), 37) }) - } -} - -impl FromBytes for UdIdV2 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let pubkey = PublicKey::try_from(&bytes[..33]) - .map_err(|e| CorruptedBytes(format!("{}: {:?}", e, bytes)))?; - let block_number = BlockNumber( - zerocopy::LayoutVerified::<_, zerocopy::U32<byteorder::BigEndian>>::new(&bytes[33..]) - .ok_or_else(|| { - CorruptedBytes( - "Corrupted DB: BlockNumber bytes are invalid length or unaligned" - .to_owned(), - ) - })? - .get(), - ); - Ok(UdIdV2(pubkey, block_number)) - } -} - -impl ToDumpString for UdIdV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for UdIdV2 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - let mut source = source.split(':'); - if let Some(pubkey_str) = source.next() { - let pubkey = PublicKey::from_base58(&pubkey_str) - .map_err(|e| FromExplorerKeyErr(format!("{}: {}", e, pubkey_str).into()))?; - if let Some(block_number_str) = source.next() { - Ok(UdIdV2( - pubkey, - BlockNumber::from_str(block_number_str) - .map_err(|e| FromExplorerKeyErr(e.into()))?, - )) - } else { - Err(FromExplorerKeyErr("UdIdV2: Invalid format".into())) - } - } else { - Err(FromExplorerKeyErr("UdIdV2: Invalid format".into())) - } - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(format!("{}:{}", self.0.to_base58(), (self.1).0)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn ud_id_v2_as_bytes() -> anyhow::Result<()> { - let ud_id = UdIdV2(PublicKey::default(), BlockNumber(3)); - - let ud_id_2_res = ud_id.as_bytes(|bytes| { - assert_eq!( - bytes, - [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 3 - ] - ); - UdIdV2::from_bytes(bytes) - }); - - assert_eq!(ud_id_2_res?, ud_id); - - Ok(()) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/uid.rs b/rust-libs/duniter-dbs/src/keys/uid.rs deleted file mode 100644 index a5e4bd7dd..000000000 --- a/rust-libs/duniter-dbs/src/keys/uid.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -const USERNAME_MAX_LEN: usize = 100; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct UidKeyV1(pub ArrayString<[u8; USERNAME_MAX_LEN]>); - -impl AsBytes for UidKeyV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.0.as_str().as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for UidKeyV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let uid_str = std::str::from_utf8(bytes).map_err(|e| CorruptedBytes(e.to_string()))?; - Ok(Self( - ArrayString::<[u8; USERNAME_MAX_LEN]>::from_str(uid_str) - .map_err(|e| CorruptedBytes(e.to_string()))?, - )) - } -} - -impl FromStr for UidKeyV1 { - type Err = arrayvec::CapacityError; - - fn from_str(source: &str) -> std::result::Result<Self, Self::Err> { - Ok(UidKeyV1(ArrayString::<[u8; USERNAME_MAX_LEN]>::from_str( - source, - )?)) - } -} - -impl ToDumpString for UidKeyV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for UidKeyV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerKeyErr(e.0.into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - self.as_bytes(|bytes| Ok(unsafe { std::str::from_utf8_unchecked(bytes) }.to_owned())) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/utxo_id.rs b/rust-libs/duniter-dbs/src/keys/utxo_id.rs deleted file mode 100644 index ca57bf0cb..000000000 --- a/rust-libs/duniter-dbs/src/keys/utxo_id.rs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use uninit::prelude::*; - -type OutputIndex = u32; - -#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] -pub struct UtxoIdDbV2(pub Hash, pub OutputIndex); - -impl PartialOrd for UtxoIdDbV2 { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - match self.0.partial_cmp(&other.0) { - Some(std::cmp::Ordering::Equal) => self.1.partial_cmp(&other.1), - o => o, - } - } -} -impl Ord for UtxoIdDbV2 { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - match self.0.cmp(&other.0) { - std::cmp::Ordering::Equal => self.1.cmp(&other.1), - o => o, - } - } -} - -impl AsBytes for UtxoIdDbV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let mut buffer = uninit_array![u8; 36]; - let (hash_buffer, index_buffer) = buffer.as_out().split_at_out(32); - let hash_buffer = hash_buffer.copy_from_slice(self.0.as_ref()); - index_buffer.copy_from_slice(&(self.1).to_be_bytes()); - f(unsafe { std::slice::from_raw_parts_mut(hash_buffer.as_mut_ptr(), 36) }) - } -} - -impl FromBytes for UtxoIdDbV2 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let hash = zerocopy::LayoutVerified::<_, Hash>::new(&bytes[..32]).ok_or_else(|| { - CorruptedBytes("Corrupted DB: Hash bytes are invalid length or unaligned".to_owned()) - })?; - let output_index = - zerocopy::LayoutVerified::<_, zerocopy::U32<byteorder::BigEndian>>::new(&bytes[32..]) - .ok_or_else(|| { - CorruptedBytes( - "Corrupted DB: OutputIndex bytes are invalid length or unaligned" - .to_owned(), - ) - })? - .get(); - Ok(UtxoIdDbV2(*hash, output_index)) - } -} - -impl ToDumpString for UtxoIdDbV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for UtxoIdDbV2 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - let mut source = source.split(':'); - if let Some(hash_str) = source.next() { - let hash = Hash::from_hex(&hash_str) - .map_err(|e| FromExplorerKeyErr(format!("{}: {}", e, hash_str).into()))?; - if let Some(output_index_str) = source.next() { - Ok(UtxoIdDbV2( - hash, - u32::from_str(output_index_str).map_err(|e| FromExplorerKeyErr(e.into()))?, - )) - } else { - Err(FromExplorerKeyErr("UtxoIdDbV2: Invalid format".into())) - } - } else { - Err(FromExplorerKeyErr("UtxoIdDbV2: Invalid format".into())) - } - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(format!("{}:{}", self.0.to_hex(), self.1)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn utxo_id_v2_as_bytes() -> anyhow::Result<()> { - let utxo_id = UtxoIdDbV2(Hash::default(), 3); - - let utxo_id_2_res = utxo_id.as_bytes(|bytes| { - assert_eq!( - bytes, - [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 - ] - ); - UtxoIdDbV2::from_bytes(bytes) - }); - - assert_eq!(utxo_id_2_res?, utxo_id); - - Ok(()) - } -} diff --git a/rust-libs/duniter-dbs/src/keys/wallet_conditions.rs b/rust-libs/duniter-dbs/src/keys/wallet_conditions.rs deleted file mode 100644 index 56af52a2a..000000000 --- a/rust-libs/duniter-dbs/src/keys/wallet_conditions.rs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -const CONDITIONS_MAX_LEN: usize = 256; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] -pub struct WalletConditionsV1(pub ArrayString<[u8; CONDITIONS_MAX_LEN]>); - -impl AsBytes for WalletConditionsV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.0.as_str().as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for WalletConditionsV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let uid_str = std::str::from_utf8(bytes).map_err(|e| CorruptedBytes(e.to_string()))?; - Ok(Self( - ArrayString::<[u8; CONDITIONS_MAX_LEN]>::from_str(uid_str) - .map_err(|e| CorruptedBytes(e.to_string()))?, - )) - } -} - -impl FromStr for WalletConditionsV1 { - type Err = arrayvec::CapacityError; - - fn from_str(source: &str) -> std::result::Result<Self, Self::Err> { - Ok(WalletConditionsV1( - ArrayString::<[u8; CONDITIONS_MAX_LEN]>::from_str(source)?, - )) - } -} - -impl ToDumpString for WalletConditionsV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for WalletConditionsV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerKeyErr(e.0.into())) - } - fn to_explorer_string(&self) -> KvResult<String> { - self.as_bytes(|bytes| Ok(unsafe { std::str::from_utf8_unchecked(bytes) }.to_owned())) - } -} - -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct WalletConditionsV2(pub WalletScriptV10); - -impl WalletConditionsV2 { - pub fn from_ref(script: &WalletScriptV10) -> &Self { - #[allow(trivial_casts)] - unsafe { - &*(script as *const WalletScriptV10 as *const WalletConditionsV2) - } - } -} - -impl AsBytes for WalletConditionsV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let mut buffer = SmallVec::<[u8; 256]>::new(); - bincode::serialize_into(&mut buffer, &self.0).unwrap_or_else(|_| unreachable!()); - f(buffer.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for WalletConditionsV2 { - type Err = bincode::Error; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - Ok(Self(bincode::deserialize(bytes)?)) - } -} - -impl ToDumpString for WalletConditionsV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for WalletConditionsV2 { - fn from_explorer_str(s: &str) -> std::result::Result<Self, FromExplorerKeyErr> { - Ok(Self( - dubp::documents_parser::wallet_script_from_str(s) - .map_err(|e| FromExplorerKeyErr(e.into()))?, - )) - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(self.0.to_string()) - } -} diff --git a/rust-libs/duniter-dbs/src/lib.rs b/rust-libs/duniter-dbs/src/lib.rs deleted file mode 100644 index 63d8a82ad..000000000 --- a/rust-libs/duniter-dbs/src/lib.rs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![allow(clippy::upper_case_acronyms)] -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -pub mod databases; -mod keys; -mod open_dbs; -mod values; - -// Re-export dependencies -pub use arrayvec; -#[cfg(feature = "explorer")] -pub use kv_typed::regex; -pub use serde; -pub use serde_json; -pub use smallvec; - -// Re-export crates -pub use kv_typed; - -// Prelude -pub mod prelude { - pub use crate::open_dbs::BackendConf; - pub use crate::SharedDbs; - #[cfg(feature = "explorer")] - pub use kv_typed::explorer::{ - DbExplorable, EntryFound, ExplorerAction, ExplorerActionResponse, ValueCaptures, - }; -} - -// Export technical types and functions -pub use crate::open_dbs::open_dbs; - -// Export profession types -pub use crate::keys::utxo_id::UtxoIdDbV2; -pub use keys::all::AllKeyV1; -pub use keys::block_number::BlockNumberKeyV1; -pub use keys::blockstamp::{BlockstampKeyV1, BlockstampKeyV2}; -pub use keys::dunp_node_id::DunpNodeIdV1Db; -pub use keys::hash::{HashKeyV1, HashKeyV2}; -pub use keys::pubkey::{PubKeyKeyV1, PubKeyKeyV2}; -pub use keys::pubkey_and_sig::PubKeyAndSigV1; -pub use keys::source_key::SourceKeyV1; -pub use keys::timestamp::TimestampKeyV1; -pub use keys::ud_id::UdIdV2; -pub use keys::uid::UidKeyV1; -pub use keys::wallet_conditions::{WalletConditionsV1, WalletConditionsV2}; -pub use values::block_db::{BlockDbEnum, BlockDbV1, BlockDbV2, TransactionInBlockDbV1}; -pub use values::block_head_db::BlockHeadDbV1; -pub use values::block_meta::BlockMetaV2; -pub use values::block_number_array_db::BlockNumberArrayV1; -pub use values::cindex_db::CIndexDbV1; -pub use values::dunp_head::DunpHeadDbV1; -pub use values::idty_db::IdtyDbV2; -pub use values::iindex_db::IIndexDbV1; -pub use values::kick_db::KickDbV1; -pub use values::mindex_db::MIndexDbV1; -pub use values::peer_card::PeerCardDbV1; -pub use values::pubkey_db::{PubKeyValV2, PublicKeyArrayDbV1, PublicKeySingletonDbV1}; -pub use values::sindex_db::{SIndexDBV1, SourceKeyArrayDbV1}; -pub use values::source_amount::SourceAmountValV2; -pub use values::tx_db::PendingTxDbV2; -pub use values::txs::BlockTxsDbV2; -pub use values::ud_entry_db::{ConsumedUdDbV1, UdAmountDbV1, UdEntryDbV1}; -pub use values::utxo::{BlockUtxosV2Db, UtxoValV2}; -pub use values::wallet_db::WalletDbV1; -pub use values::wallet_script_with_sa::WalletScriptWithSourceAmountV1Db; - -// Crate imports -pub(crate) use arrayvec::{ArrayString, ArrayVec}; -#[cfg(feature = "explorer")] -use chrono::NaiveDateTime; -pub(crate) use dubp::common::crypto::bases::b58::ToBase58 as _; -pub(crate) use dubp::common::crypto::bases::BaseConversionError; -pub(crate) use dubp::common::crypto::hashs::Hash; -pub(crate) use dubp::common::crypto::keys::ed25519::{PublicKey, Signature}; -pub(crate) use dubp::common::crypto::keys::{PublicKey as _, Signature as _}; -pub(crate) use dubp::common::prelude::*; -pub(crate) use dubp::documents::dubp_wallet::prelude::*; -pub(crate) use kv_typed::db_schema; -pub(crate) use kv_typed::prelude::*; -pub(crate) use serde::{Deserialize, Serialize}; -pub(crate) use smallvec::SmallVec; -pub(crate) use std::{ - collections::BTreeSet, convert::TryFrom, fmt::Debug, iter::Iterator, num::ParseIntError, - path::Path, str::FromStr, -}; - -#[derive(Debug, Error)] -#[error("{0}")] -pub struct CorruptedBytes(pub String); - -pub trait ToDumpString { - fn to_dump_string(&self) -> String; -} - -#[cfg(all(not(feature = "mem"), not(test)))] -pub type FileBackend = kv_typed::backend::sled::Sled; -#[cfg(any(feature = "mem", test))] -pub type FileBackend = kv_typed::backend::memory::Mem; - -#[derive(Clone, Debug)] -pub struct SharedDbs<B: Backend> { - pub bc_db_ro: databases::bc_v2::BcV2DbRo<B>, - pub cm_db: databases::cm_v1::CmV1Db<MemSingleton>, - pub dunp_db: databases::network_v1::NetworkV1Db<B>, - pub txs_mp_db: databases::txs_mp_v2::TxsMpV2Db<B>, -} - -impl SharedDbs<Mem> { - pub fn mem() -> KvResult<Self> { - use databases::bc_v2::BcV2DbWritable as _; - use databases::cm_v1::CmV1DbWritable as _; - use databases::network_v1::NetworkV1DbWritable as _; - use databases::txs_mp_v2::TxsMpV2DbWritable as _; - Ok(SharedDbs { - bc_db_ro: databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?.get_ro_handler(), - cm_db: databases::cm_v1::CmV1Db::<MemSingleton>::open(MemSingletonConf::default())?, - dunp_db: databases::network_v1::NetworkV1Db::<Mem>::open(MemConf::default())?, - txs_mp_db: databases::txs_mp_v2::TxsMpV2Db::<Mem>::open(MemConf::default())?, - }) - } -} diff --git a/rust-libs/duniter-dbs/src/open_dbs.rs b/rust-libs/duniter-dbs/src/open_dbs.rs deleted file mode 100644 index 05f1ffd1b..000000000 --- a/rust-libs/duniter-dbs/src/open_dbs.rs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::databases::bc_v2::BcV2DbWritable as _; -use crate::databases::cm_v1::CmV1DbWritable as _; -use crate::databases::network_v1::NetworkV1DbWritable as _; -use crate::databases::txs_mp_v2::TxsMpV2DbWritable as _; -use crate::*; - -pub fn open_dbs<B: BackendConf>( - profile_path_opt: Option<&Path>, -) -> KvResult<(crate::databases::bc_v2::BcV2Db<B>, SharedDbs<B>)> { - let bc_db = crate::databases::bc_v2::BcV2Db::<B>::open(B::gen_backend_conf( - crate::databases::bc_v2::BcV2Db::<B>::NAME, - profile_path_opt, - ))?; - let dbs = SharedDbs { - bc_db_ro: bc_db.get_ro_handler(), - cm_db: crate::databases::cm_v1::CmV1Db::<MemSingleton>::open(MemSingletonConf::default()) - .expect("fail to open CmV1 DB"), - dunp_db: crate::databases::network_v1::NetworkV1Db::<B>::open(B::gen_backend_conf( - "dunp_v1", - profile_path_opt, - ))?, - txs_mp_db: crate::databases::txs_mp_v2::TxsMpV2Db::<B>::open(B::gen_backend_conf( - crate::databases::txs_mp_v2::TxsMpV2Db::<B>::NAME, - profile_path_opt, - ))?, - }; - Ok((bc_db, dbs)) -} - -pub trait BackendConf: Backend { - fn gen_backend_conf( - db_name: &'static str, - profile_path_opt: Option<&Path>, - ) -> <Self as Backend>::Conf; -} - -impl BackendConf for Mem { - #[inline(always)] - fn gen_backend_conf(_db_name: &'static str, _profile_path_opt: Option<&Path>) -> MemConf { - MemConf::default() - } -} - -/*impl BackendConf for Lmdb { - #[inline(always)] - fn gen_backend_conf(db_name: &'static str, profile_path_opt: Option<&Path>) -> LmdbConf { - let conf = LmdbConf::default(); - if let Some(data_path) = profile_path_opt { - conf.folder_path(data_path.join(format!("data/{}_lmdb", db_name))) - } else { - let random = rand::random::<u128>(); - conf.folder_path(PathBuf::from(format!( - "/dev/shm/duniter/_{}/{}_lmdb", - random, db_name - ))) - .temporary(true) - } - } -}*/ - -impl BackendConf for Sled { - #[inline(always)] - fn gen_backend_conf(db_name: &'static str, profile_path_opt: Option<&Path>) -> SledConf { - let mut conf = SledConf::default().flush_every_ms(Some(10_000)); - conf = match db_name { - "bc_v2" => { - if let Ok(compression_level) = std::env::var("DUNITER_BC_DB_COMPRESSION") { - conf.use_compression(true) - .compression_factor(i32::from_str(&compression_level).expect( - "Env var DUNITER_BC_DB_COMPRESSION must be a number beetween 1 and 22 !", - )) - } else { - conf.use_compression(false) - } - } - "gva_v1" => { - if let Ok(compression_level) = std::env::var("DUNITER_GVA_DB_COMPRESSION") { - conf.use_compression(true) - .compression_factor(i32::from_str(&compression_level).expect( - "Env var DUNITER_GVA_DB_COMPRESSION must be a number beetween 1 and 22 !", - )) - } else { - conf.use_compression(false) - } - } - _ => conf.use_compression(false), - }; - if let Some(data_path) = profile_path_opt { - conf.path(data_path.join(format!("data/{}_sled", db_name))) - } else { - conf.temporary(true) - } - } -} diff --git a/rust-libs/duniter-dbs/src/values.rs b/rust-libs/duniter-dbs/src/values.rs deleted file mode 100644 index a77cb7fd2..000000000 --- a/rust-libs/duniter-dbs/src/values.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -pub mod block_db; -pub mod block_head_db; -pub mod block_meta; -pub mod block_number_array_db; -pub mod cindex_db; -pub mod dunp_head; -pub mod idty_db; -pub mod iindex_db; -pub mod kick_db; -pub mod mindex_db; -pub mod peer_card; -pub mod pubkey_db; -pub mod sindex_db; -pub mod source_amount; -pub mod tx_db; -pub mod txs; -pub mod ud_entry_db; -pub mod utxo; -pub mod wallet_db; -pub mod wallet_script_with_sa; diff --git a/rust-libs/duniter-dbs/src/values/block_db.rs b/rust-libs/duniter-dbs/src/values/block_db.rs deleted file mode 100644 index c288cda97..000000000 --- a/rust-libs/duniter-dbs/src/values/block_db.rs +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Debug)] -pub enum BlockDbEnum { - BlockDbV1(BlockDbV1), -} - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct BlockDbV1 { - pub version: u64, - pub number: u64, - pub currency: String, - pub hash: String, - pub signature: String, - #[serde(rename = "inner_hash")] - pub inner_hash: String, - pub previous_hash: Option<String>, - pub issuer: String, - pub previous_issuer: Option<String>, - pub time: u64, - pub pow_min: u64, - #[serde(rename = "unitbase")] - pub unit_base: u64, - pub members_count: u64, - pub issuers_count: u64, - pub issuers_frame: u64, - pub issuers_frame_var: i64, - pub identities: Vec<String>, - pub joiners: Vec<String>, - pub actives: Vec<String>, - pub leavers: Vec<String>, - pub revoked: Vec<String>, - pub excluded: Vec<String>, - pub certifications: Vec<String>, - pub transactions: Vec<TransactionInBlockDbV1>, - pub median_time: u64, - pub nonce: u64, - pub fork: bool, - pub parameters: String, - pub monetary_mass: u64, - pub dividend: Option<u64>, - #[serde(rename = "UDTime")] - pub ud_time: Option<u64>, - #[serde(rename = "writtenOn")] - pub written_on: Option<u64>, - #[serde(rename = "written_on")] - pub written_on_str: String, - pub wrong: bool, -} - -impl AsBytes for BlockDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json = serde_json::to_string(self).expect("unreachable"); - f(json.as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for BlockDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for BlockDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for BlockDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct TransactionInBlockDbV1 { - version: u64, - currency: String, - #[serde(rename = "locktime")] - lock_time: u64, - hash: Option<String>, - blockstamp: String, - blockstamp_time: u64, - issuers: SmallVec<[String; 1]>, - inputs: SmallVec<[String; 4]>, - outputs: SmallVec<[String; 2]>, - unlocks: SmallVec<[String; 4]>, - signatures: SmallVec<[String; 1]>, - comment: String, -} - -// V2 - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -pub struct BlockDbV2(pub dubp::block::DubpBlockV10); - -impl AsBytes for BlockDbV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let bytes = bincode::serialize(self).unwrap_or_else(|_| unreachable!()); - f(bytes.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for BlockDbV2 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(&bytes).map_err(|e| CorruptedBytes(format!("{}: '{:?}'", e, bytes))) - } -} - -impl ToDumpString for BlockDbV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for BlockDbV2 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - serde_json::from_str(source).map_err(|e| FromExplorerValueErr(e.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/block_head_db.rs b/rust-libs/duniter-dbs/src/values/block_head_db.rs deleted file mode 100644 index 97c3f6a04..000000000 --- a/rust-libs/duniter-dbs/src/values/block_head_db.rs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct BlockHeadDbV1 { - pub version: u64, - pub currency: Option<String>, - #[serde(rename = "bsize")] - pub block_size: u64, - pub avg_block_size: u64, - pub ud_time: u64, - pub ud_reeval_time: u64, - pub mass_reeval: u64, - pub mass: u64, - pub hash: String, - pub previous_hash: Option<String>, - pub previous_issuer: Option<String>, - pub issuer: String, - pub time: u64, - pub median_time: u64, - pub number: u64, - pub pow_min: u64, - pub diff_number: u64, - pub issuers_count: u64, - pub issuers_frame: u64, - pub issuers_frame_var: i64, - pub issuer_diff: u64, - pub pow_zeros: u64, - pub pow_remainder: u64, - pub speed: f64, - pub unit_base: u64, - pub members_count: u64, - pub dividend: u64, - #[serde(rename = "new_dividend")] - pub new_dividend: Option<u64>, - pub issuer_is_member: bool, -} - -impl AsBytes for BlockHeadDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json = serde_json::to_string(self).unwrap_or_else(|_| unreachable!()); - f(json.as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for BlockHeadDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for BlockHeadDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for BlockHeadDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/block_meta.rs b/rust-libs/duniter-dbs/src/values/block_meta.rs deleted file mode 100644 index 949a644d9..000000000 --- a/rust-libs/duniter-dbs/src/values/block_meta.rs +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use dubp::block::DubpBlockV10; - -use crate::*; - -const BLOCK_META_SERIALIZED_SIZE: usize = 323; - -#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize)] -pub struct BlockMetaV2 { - pub version: u64, // 8 - pub number: u32, // 4 - pub hash: Hash, // 32 - pub signature: Signature, // 64 - pub inner_hash: Hash, // 32 - pub previous_hash: Hash, // 32 - pub issuer: PublicKey, // 33 - pub previous_issuer: PublicKey, // 33 - pub time: u64, // 8 - pub pow_min: u32, // 4 - pub members_count: u64, // 8 - pub issuers_count: u32, // 4 - pub issuers_frame: u64, // 8 - pub issuers_frame_var: i64, // 8 - pub median_time: u64, // 8 - pub nonce: u64, // 8 - pub monetary_mass: u64, // 8 - pub unit_base: u32, // 4 - pub dividend: Option<SourceAmount>, // 17 -> TOTAL SIZE == 335 bytes -} -impl BlockMetaV2 { - pub fn blockstamp(&self) -> Blockstamp { - Blockstamp { - number: BlockNumber(self.number), - hash: BlockHash(self.hash), - } - } -} - -impl AsBytes for BlockMetaV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let mut buffer = [0u8; BLOCK_META_SERIALIZED_SIZE]; - bincode::serialize_into(&mut buffer[..], self).unwrap_or_else(|_| unreachable!()); - f(buffer.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for BlockMetaV2 { - type Err = bincode::Error; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(bytes) - } -} - -impl ToDumpString for BlockMetaV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for BlockMetaV2 { - fn from_explorer_str(json_str: &str) -> std::result::Result<Self, FromExplorerValueErr> { - serde_json::from_str(&json_str) - .map_err(|e| FromExplorerValueErr(format!("{}: '{}'", e, json_str).into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use unwrap::unwrap; - - #[test] - fn block_meta_v2_as_bytes() { - assert_eq!( - unwrap!(bincode::serialized_size(&BlockMetaV2 { - dividend: Some(SourceAmount::new(42, 0)), - ..Default::default() - })), - BLOCK_META_SERIALIZED_SIZE as u64 - ); - let bloc_meta = BlockMetaV2::default(); - - let bm2_res = bloc_meta.as_bytes(|bytes| unwrap!(BlockMetaV2::from_bytes(bytes))); - - assert_eq!(bm2_res, bloc_meta); - } -} - -impl From<&DubpBlockV10> for BlockMetaV2 { - fn from(block: &DubpBlockV10) -> Self { - use dubp::block::prelude::DubpBlockTrait; - BlockMetaV2 { - version: 10, - number: block.number().0, - hash: block.hash().0, - signature: block.signature(), - inner_hash: block.inner_hash(), - previous_hash: block.previous_hash(), - issuer: block.issuer(), - previous_issuer: PublicKey::default(), - time: block.local_time(), - pow_min: block.pow_min() as u32, - members_count: block.members_count() as u64, - issuers_count: block.issuers_count() as u32, - issuers_frame: block.issuers_frame() as u64, - issuers_frame_var: 0, - median_time: block.common_time(), - nonce: block.nonce(), - monetary_mass: block.monetary_mass(), - dividend: block.dividend(), - unit_base: block.unit_base() as u32, - } - } -} diff --git a/rust-libs/duniter-dbs/src/values/block_number_array_db.rs b/rust-libs/duniter-dbs/src/values/block_number_array_db.rs deleted file mode 100644 index e4b5f0c36..000000000 --- a/rust-libs/duniter-dbs/src/values/block_number_array_db.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub struct BlockNumberArrayV1(pub SmallVec<[BlockNumber; 1]>); - -impl AsBytes for BlockNumberArrayV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json_string = serde_json::to_string(self).unwrap_or_else(|_| unreachable!()); - f(format!("[{}]", json_string).as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for BlockNumberArrayV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - //println!("json_str='{}'", &json_str); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for BlockNumberArrayV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for BlockNumberArrayV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/cindex_db.rs b/rust-libs/duniter-dbs/src/values/cindex_db.rs deleted file mode 100644 index ded4657e5..000000000 --- a/rust-libs/duniter-dbs/src/values/cindex_db.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub struct CIndexDbV1 { - pub received: SmallVec<[String; 10]>, - pub issued: Vec<CIndexLineDbV1>, -} - -impl AsBytes for CIndexDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json_string = serde_json::to_string(self).unwrap_or_else(|_| unreachable!()); - f(format!("[{}]", json_string).as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for CIndexDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - //println!("json_str='{}'", &json_str); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for CIndexDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for CIndexDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct CIndexLineDbV1 { - pub op: String, - #[serde(rename = "writtenOn")] - pub written_on: Option<u64>, - #[serde(rename = "written_on")] - pub written_on_str: String, - pub issuer: String, - pub receiver: String, - #[serde(rename = "created_on")] - pub created_on: u64, - pub sig: Option<String>, - #[serde(rename = "chainable_on")] - pub chainable_on: Option<u64>, - #[serde(rename = "replayable_on")] - pub replayable_on: Option<u64>, - #[serde(rename = "expires_on")] - pub expires_on: Option<u64>, - #[serde(rename = "expired_on")] - pub expired_on: u64, - pub unchainables: Option<u64>, - pub age: Option<u64>, - pub stock: Option<u64>, - pub from_member: Option<bool>, - pub to_member: Option<bool>, - pub to_newcomer: Option<bool>, - pub to_leaver: Option<bool>, - pub is_replay: Option<bool>, - pub is_replayable: Option<bool>, - #[serde(rename = "sigOK")] - pub sig_ok: Option<bool>, - #[serde(rename = "created_on_ref")] - pub created_on_ref: Option<CreatedOnRef>, -} - -#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct CreatedOnRef { - pub median_time: u64, -} diff --git a/rust-libs/duniter-dbs/src/values/dunp_head.rs b/rust-libs/duniter-dbs/src/values/dunp_head.rs deleted file mode 100644 index bf42b21a4..000000000 --- a/rust-libs/duniter-dbs/src/values/dunp_head.rs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -pub struct DunpHeadDbV1 { - pub api: String, - pub pubkey: PublicKey, - pub blockstamp: Blockstamp, - pub software: String, - pub software_version: String, - pub pow_prefix: u32, - pub free_member_room: u32, - pub free_mirror_room: u32, - pub signature: Signature, -} - -impl DunpHeadDbV1 { - pub fn from_stringified(message_v2: &str, signature: &str) -> KvResult<(DunpNodeIdV1Db, Self)> { - let signature = - Signature::from_base64(signature).map_err(|e| KvError::DeserError(e.into()))?; - - let strs: SmallVec<[&str; 11]> = message_v2.split(':').collect(); - if strs.len() < 11 { - return Err(KvError::DeserError( - "DunpHeadDbV1::from_stringified(): invalid message_v2".into(), - )); - } - - let uuid = u32::from_str_radix(strs[5], 16).map_err(|e| KvError::DeserError(e.into()))?; - let pubkey = PublicKey::from_base58(strs[3]).map_err(|e| KvError::DeserError(e.into()))?; - let blockstamp = - Blockstamp::from_str(strs[4]).map_err(|e| KvError::DeserError(e.into()))?; - - Ok(( - DunpNodeIdV1Db::new(uuid, pubkey), - DunpHeadDbV1 { - api: strs[0].to_owned(), - pubkey, - blockstamp, - software: strs[6].to_owned(), - software_version: strs[7].to_owned(), - pow_prefix: u32::from_str(strs[8]).map_err(|e| KvError::DeserError(e.into()))?, - free_member_room: u32::from_str(strs[9]) - .map_err(|e| KvError::DeserError(e.into()))?, - free_mirror_room: u32::from_str(strs[10]) - .map_err(|e| KvError::DeserError(e.into()))?, - signature, - }, - )) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_dunp_head_from_stringified() -> KvResult<()> { - let message = "WS2POCAIC:HEAD:2:GX1nYVburxeaVP1SCNuhVKwNy6M2h6wPamHhyoSF4Ccn:379783-0000001BB2B88D077605C1330CA60AA222624FAA3BA60566D6CA51A9122376F7:882a5ad1:duniter:1.8.1:1:1:1"; - let sig = "qBvJ7JZ4i8tKeItmZ/lurzr5O2/jKnB1reoIjEIl5x6sqbAhVsVsHut85yQoP30tURGfVX5FwMhCuC4DvCSFCg=="; - let (node_id, head) = DunpHeadDbV1::from_stringified(message, sig)?; - - assert_eq!(&format!("{:x}", node_id.get_uuid()), "882a5ad1"); - assert_eq!( - &node_id.get_pubkey().to_string(), - "GX1nYVburxeaVP1SCNuhVKwNy6M2h6wPamHhyoSF4Ccn" - ); - assert_eq!(&head.api, "WS2POCAIC"); - assert_eq!( - &head.pubkey.to_string(), - "GX1nYVburxeaVP1SCNuhVKwNy6M2h6wPamHhyoSF4Ccn" - ); - assert_eq!( - &head.blockstamp.to_string(), - "379783-0000001BB2B88D077605C1330CA60AA222624FAA3BA60566D6CA51A9122376F7" - ); - Ok(()) - } -} - -impl AsBytes for DunpHeadDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let bytes = bincode::serialize(self).unwrap_or_else(|_| unreachable!()); - f(bytes.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for DunpHeadDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(&bytes).map_err(|e| CorruptedBytes(format!("{}: '{:?}'", e, bytes))) - } -} - -impl ToDumpString for DunpHeadDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for DunpHeadDbV1 { - fn from_explorer_str(_source: &str) -> std::result::Result<Self, FromExplorerValueErr> { - unimplemented!() - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/idty_db.rs b/rust-libs/duniter-dbs/src/values/idty_db.rs deleted file mode 100644 index 504f79950..000000000 --- a/rust-libs/duniter-dbs/src/values/idty_db.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] -pub struct IdtyDbV2 { - pub is_member: bool, - pub username: String, -} - -impl AsBytes for IdtyDbV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(&bincode::serialize(&self).unwrap_or_else(|_| unreachable!())) - } -} - -impl kv_typed::prelude::FromBytes for IdtyDbV2 { - type Err = bincode::Error; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(bytes) - } -} - -impl ToDumpString for IdtyDbV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for IdtyDbV2 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - serde_json::from_str(source).map_err(|e| FromExplorerValueErr(e.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(&self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/iindex_db.rs b/rust-libs/duniter-dbs/src/values/iindex_db.rs deleted file mode 100644 index 947494fbd..000000000 --- a/rust-libs/duniter-dbs/src/values/iindex_db.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub struct IIndexDbV1(pub SmallVec<[IIndexLineDbV1; 1]>); - -impl AsBytes for IIndexDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json_string = serde_json::to_string(self).unwrap_or_else(|_| unreachable!()); - f(format!("[{}]", json_string).as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for IIndexDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - //println!("json_str='{}'", &json_str); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for IIndexDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for IIndexDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct IIndexLineDbV1 { - pub op: String, - #[serde(rename = "writtenOn")] - pub written_on: Option<u64>, - #[serde(rename = "written_on")] - pub written_on_str: String, - pub uid: Option<String>, - #[serde(rename = "pub")] - pub pubkey: String, - pub hash: Option<String>, - pub sig: Option<String>, - #[serde(rename = "created_on")] - pub created_on: Option<String>, - pub member: Option<bool>, - pub was_member: Option<bool>, - pub kick: Option<bool>, - #[serde(rename = "wotb_id")] - pub wotb_id: Option<usize>, - pub age: Option<u64>, - pub pub_unique: Option<bool>, - pub excluded_is_member: Option<bool>, - pub is_being_kicked: Option<bool>, - pub uid_unique: Option<bool>, - pub has_to_be_excluded: Option<bool>, -} diff --git a/rust-libs/duniter-dbs/src/values/kick_db.rs b/rust-libs/duniter-dbs/src/values/kick_db.rs deleted file mode 100644 index b616cdc75..000000000 --- a/rust-libs/duniter-dbs/src/values/kick_db.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -pub struct KickDbV1 { - on: Option<u64>, // The next time that the identity must be kicked - done: SmallVec<[u64; 4]>, // The reversion history -} - -impl AsBytes for KickDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json = serde_json::to_string(self).unwrap_or_else(|_| unreachable!()); - f(json.as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for KickDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for KickDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for KickDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/mindex_db.rs b/rust-libs/duniter-dbs/src/values/mindex_db.rs deleted file mode 100644 index eb7d42a35..000000000 --- a/rust-libs/duniter-dbs/src/values/mindex_db.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub struct MIndexDbV1(pub SmallVec<[MIndexLineDbV1; 1]>); - -impl AsBytes for MIndexDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json_string = serde_json::to_string(self).unwrap_or_else(|_| unreachable!()); - f(format!("[{}]", json_string).as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for MIndexDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - //println!("json_str='{}'", &json_str); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for MIndexDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for MIndexDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct MIndexLineDbV1 { - pub op: String, - #[serde(rename = "writtenOn")] - pub written_on: Option<u64>, - #[serde(rename = "written_on")] - pub written_on_str: String, - #[serde(rename = "pub")] - pub pubkey: String, - pub created_on: Option<String>, - #[serde(rename = "type")] - pub r#type: Option<String>, - #[serde(rename = "expires_on")] - pub expires_on: Option<u64>, - #[serde(rename = "expired_on")] - pub expired_on: Option<u64>, - pub revocation: Option<String>, - #[serde(rename = "revokes_on")] - pub revokes_on: Option<u64>, - #[serde(rename = "chainable_on")] - pub chainable_on: Option<u64>, - #[serde(rename = "revoked_on")] - pub revoked_on: Option<String>, - pub leaving: Option<bool>, - pub age: Option<u64>, - pub is_being_revoked: Option<bool>, - pub unchainables: Option<u64>, - pub number_following: Option<bool>, - #[serde(rename = "distanceOK")] - pub distance_ok: Option<bool>, - pub on_revoked: Option<bool>, - pub joins_twice: Option<bool>, - pub enough_certs: Option<bool>, - pub leaver_is_member: Option<bool>, - pub active_is_member: Option<bool>, - pub revoked_is_member: Option<bool>, - pub already_revoked: Option<bool>, - #[serde(rename = "revocationSigOK")] - pub revocation_sig_ok: Option<bool>, - #[serde(rename = "created_on_ref")] - pub created_on_ref: Option<BlockstampTimed>, -} - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct BlockstampTimed { - pub median_time: u64, - pub number: u32, - pub hash: String, -} diff --git a/rust-libs/duniter-dbs/src/values/peer_card.rs b/rust-libs/duniter-dbs/src/values/peer_card.rs deleted file mode 100644 index ee08696d7..000000000 --- a/rust-libs/duniter-dbs/src/values/peer_card.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -pub struct PeerCardDbV1 { - pub version: u32, - pub currency: String, - pub pubkey: String, - pub blockstamp: String, - pub endpoints: Vec<String>, - pub status: String, - pub signature: String, -} - -impl AsBytes for PeerCardDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let bytes = bincode::serialize(self).unwrap_or_else(|_| unreachable!()); - f(bytes.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for PeerCardDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(&bytes).map_err(|e| CorruptedBytes(format!("{}: '{:?}'", e, bytes))) - } -} - -impl ToDumpString for PeerCardDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for PeerCardDbV1 { - fn from_explorer_str(_source: &str) -> std::result::Result<Self, FromExplorerValueErr> { - unimplemented!() - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/pubkey_db.rs b/rust-libs/duniter-dbs/src/values/pubkey_db.rs deleted file mode 100644 index 7c16eedd6..000000000 --- a/rust-libs/duniter-dbs/src/values/pubkey_db.rs +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -// V1 - -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct PublicKeySingletonDbV1(pub PublicKey); - -impl AsBytes for PublicKeySingletonDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(format!("[\"{}\"]", self.0).as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for PublicKeySingletonDbV1 { - type Err = BaseConversionError; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let mut pubkey_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - - pubkey_str = &pubkey_str[2..pubkey_str.len() - 2]; - Ok(Self(PublicKey::from_base58(pubkey_str)?)) - } -} - -impl ToDumpString for PublicKeySingletonDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for PublicKeySingletonDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Ok(Self( - PublicKey::from_base58(source).map_err(|e| FromExplorerValueErr(e.into()))?, - )) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::String(self.0.to_base58())) - } -} - -#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub struct PublicKeyArrayDbV1(pub SmallVec<[PublicKey; 8]>); - -impl AsBytes for PublicKeyArrayDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let vec_pub_str = self - .0 - .iter() - .map(|pubkey| pubkey.to_base58()) - .collect::<SmallVec<[String; 8]>>(); - let json = serde_json::to_string(&vec_pub_str).unwrap_or_else(|_| unreachable!()); - f(json.as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for PublicKeyArrayDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - let vec_pub_str: SmallVec<[String; 8]> = serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str)))?; - Ok(Self( - vec_pub_str - .into_iter() - .map(|pub_str| { - PublicKey::from_base58(&pub_str).map_err(|e| CorruptedBytes(e.to_string())) - }) - .collect::<std::result::Result<SmallVec<[PublicKey; 8]>, Self::Err>>()?, - )) - } -} - -impl ToDumpString for PublicKeyArrayDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for PublicKeyArrayDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::Array( - self.0 - .iter() - .map(|pubkey| serde_json::Value::String(pubkey.to_base58())) - .collect(), - )) - } -} - -// V2 - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct PubKeyValV2(pub PublicKey); - -impl AsBytes for PubKeyValV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.0.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for PubKeyValV2 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - Ok(PubKeyValV2(PublicKey::try_from(bytes).map_err(|e| { - CorruptedBytes(format!("{}: {:?}", e, bytes)) - })?)) - } -} - -impl ToDumpString for PubKeyValV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for PubKeyValV2 { - fn from_explorer_str(pubkey_str: &str) -> std::result::Result<Self, FromExplorerValueErr> { - Ok(PubKeyValV2(PublicKey::from_base58(&pubkey_str).map_err( - |e| FromExplorerValueErr(format!("{}: {}", e, pubkey_str).into()), - )?)) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::String(self.0.to_base58())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/sindex_db.rs b/rust-libs/duniter-dbs/src/values/sindex_db.rs deleted file mode 100644 index 4d5b9f204..000000000 --- a/rust-libs/duniter-dbs/src/values/sindex_db.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct SIndexDBV1 { - pub src_type: String, - pub tx: Option<String>, - pub identifier: String, - pub pos: u32, - #[serde(rename = "created_on")] - pub created_on: Option<String>, - #[serde(rename = "written_time")] - pub written_time: u64, - #[serde(rename = "locktime")] - pub lock_time: u64, - pub unlock: Option<String>, - pub amount: u32, - pub base: u32, - pub conditions: String, - pub consumed: bool, - pub tx_obj: TransactionInBlockDbV1, - pub age: u64, - #[serde(rename = "type")] - pub type_: Option<String>, - pub available: Option<bool>, - pub is_locked: Option<bool>, - pub is_time_locked: Option<bool>, -} - -impl AsBytes for SIndexDBV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json = serde_json::to_string(self).unwrap_or_else(|_| unreachable!()); - f(json.as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for SIndexDBV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for SIndexDBV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for SIndexDBV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} - -#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub struct SourceKeyArrayDbV1(pub SmallVec<[SourceKeyV1; 8]>); - -impl AsBytes for SourceKeyArrayDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let vec_pub_str = self - .0 - .iter() - .map(|source_key| source_key.to_string()) - .collect::<SmallVec<[String; 8]>>(); - let json = serde_json::to_string(&vec_pub_str).unwrap_or_else(|_| unreachable!()); - f(json.as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for SourceKeyArrayDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - let vec_source_key_str: SmallVec<[String; 8]> = serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str)))?; - Ok(Self( - vec_source_key_str - .into_iter() - .map(|source_key_str| SourceKeyV1::from_bytes(source_key_str.as_bytes())) - .collect::<std::result::Result<SmallVec<[SourceKeyV1; 8]>, Self::Err>>()?, - )) - } -} - -impl ToDumpString for SourceKeyArrayDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for SourceKeyArrayDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/source_amount.rs b/rust-libs/duniter-dbs/src/values/source_amount.rs deleted file mode 100644 index 331493f7d..000000000 --- a/rust-libs/duniter-dbs/src/values/source_amount.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Default, PartialEq)] -pub struct SourceAmountValV2(pub SourceAmount); - -impl AsBytes for SourceAmountValV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - use zerocopy::AsBytes as _; - f(self.0.as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for SourceAmountValV2 { - type Err = LayoutVerifiedErr; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let layout = zerocopy::LayoutVerified::<_, SourceAmount>::new(bytes) - .ok_or(LayoutVerifiedErr(stringify!(SourceAmount)))?; - Ok(Self(*layout)) - } -} - -impl ToDumpString for SourceAmountValV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for SourceAmountValV2 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - let mut source = source.split(':'); - let amount_str = source - .next() - .ok_or_else(|| FromExplorerValueErr("Missing amount".into()))?; - let base_str = source - .next() - .ok_or_else(|| FromExplorerValueErr("Missing base".into()))?; - let amount = i64::from_str(amount_str) - .map_err(|e| FromExplorerValueErr(format!("Invalid amount: {}", e).into()))?; - let base = i64::from_str(base_str) - .map_err(|e| FromExplorerValueErr(format!("Invalid base: {}", e).into()))?; - Ok(Self(SourceAmount::new(amount, base))) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::String(format!( - "{}:{}", - self.0.amount(), - self.0.base() - ))) - } -} diff --git a/rust-libs/duniter-dbs/src/values/tx_db.rs b/rust-libs/duniter-dbs/src/values/tx_db.rs deleted file mode 100644 index bcc06d149..000000000 --- a/rust-libs/duniter-dbs/src/values/tx_db.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -use dubp::documents::transaction::TransactionDocumentV10; -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -pub struct PendingTxDbV2(pub TransactionDocumentV10); - -impl AsBytes for PendingTxDbV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let bytes = bincode::serialize(self).unwrap_or_else(|_| unreachable!()); - f(bytes.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for PendingTxDbV2 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(&bytes).map_err(|e| CorruptedBytes(format!("{}: '{:?}'", e, bytes))) - } -} - -impl ToDumpString for PendingTxDbV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for PendingTxDbV2 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/txs.rs b/rust-libs/duniter-dbs/src/values/txs.rs deleted file mode 100644 index f150673ef..000000000 --- a/rust-libs/duniter-dbs/src/values/txs.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -use dubp::documents::transaction::TransactionDocumentV10; -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -pub struct BlockTxsDbV2(pub SmallVec<[TransactionDocumentV10; 8]>); - -impl AsBytes for BlockTxsDbV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let bytes = bincode::serialize(self).unwrap_or_else(|_| unreachable!()); - f(bytes.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for BlockTxsDbV2 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(&bytes).map_err(|e| CorruptedBytes(format!("{}: '{:?}'", e, bytes))) - } -} - -impl ToDumpString for BlockTxsDbV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for BlockTxsDbV2 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - serde_json::from_str(source).map_err(|e| FromExplorerValueErr(e.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/ud_entry_db.rs b/rust-libs/duniter-dbs/src/values/ud_entry_db.rs deleted file mode 100644 index a32efd774..000000000 --- a/rust-libs/duniter-dbs/src/values/ud_entry_db.rs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct UdEntryDbV1 { - #[serde(rename = "pub")] - pub pubkey: String, - pub member: bool, - pub availables: Vec<u32>, - pub consumed: Vec<u32>, - #[serde(rename = "consumedUDs")] - pub consumed_uds: Vec<ConsumedUdDbV1>, - pub dividends: Vec<UdAmountDbV1>, -} - -impl AsBytes for UdEntryDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json = serde_json::to_string(self).unwrap_or_else(|_| unreachable!()); - f(json.as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for UdEntryDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for UdEntryDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for UdEntryDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ConsumedUdDbV1 { - pub dividend_number: u32, - pub tx_hash: String, - pub tx_created_on: String, - #[serde(rename = "txLocktime")] - pub tx_lock_time: u32, - pub dividend: UdAmountDbV1, -} - -#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize)] -pub struct UdAmountDbV1 { - pub amount: u32, - pub base: u32, -} diff --git a/rust-libs/duniter-dbs/src/values/utxo.rs b/rust-libs/duniter-dbs/src/values/utxo.rs deleted file mode 100644 index dc5b60e56..000000000 --- a/rust-libs/duniter-dbs/src/values/utxo.rs +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use std::{collections::HashMap, ops::Deref}; - -#[derive( - Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, zerocopy::AsBytes, zerocopy::FromBytes, -)] -#[repr(transparent)] -pub struct UtxoValV2([u8; 52]); // 16(SourceAmount) + 32(Hash) + 4(u32) -impl UtxoValV2 { - pub fn new(amount: SourceAmount, tx_hash: Hash, output_index: u32) -> Self { - let mut buffer = [0; 52]; - use zerocopy::AsBytes as _; - buffer[..16].copy_from_slice(amount.as_bytes()); - buffer[16..48].copy_from_slice(tx_hash.as_ref()); - buffer[48..].copy_from_slice(&output_index.to_le_bytes()[..]); - Self(buffer) - } - pub fn amount(&self) -> &SourceAmount { - let layout = - zerocopy::LayoutVerified::<_, SourceAmount>::new(&self.0[..16]).expect("dev error"); - - unsafe { std::mem::transmute(layout.deref()) } - } - pub fn tx_hash(&self) -> &Hash { - let layout = zerocopy::LayoutVerified::<_, Hash>::new(&self.0[16..48]).expect("dev error"); - - unsafe { std::mem::transmute(layout.deref()) } - } - pub fn output_index(&self) -> u32 { - zerocopy::LayoutVerified::<_, zerocopy::U32<byteorder::LittleEndian>>::new(&self.0[48..]) - .expect("dev error") - .get() - } -} - -impl Default for UtxoValV2 { - fn default() -> Self { - UtxoValV2([0u8; 52]) - } -} - -impl std::fmt::Display for UtxoValV2 { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let amount = self.amount(); - write!( - f, - "{}:{}:T:{}:{}", - amount.amount(), - amount.base(), - self.tx_hash(), - self.output_index() - ) - } -} - -impl FromStr for UtxoValV2 { - type Err = CorruptedBytes; - - fn from_str(_s: &str) -> std::result::Result<Self, Self::Err> { - unimplemented!() - } -} - -impl AsBytes for UtxoValV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.0.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for UtxoValV2 { - type Err = LayoutVerifiedErr; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let layout = zerocopy::LayoutVerified::<_, UtxoValV2>::new(bytes) - .ok_or(LayoutVerifiedErr(stringify!(UtxoValV2)))?; - Ok(*layout) - } -} - -impl ToDumpString for UtxoValV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for UtxoValV2 { - fn from_explorer_str(_: &str) -> std::result::Result<Self, FromExplorerValueErr> { - unimplemented!() - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::String(self.to_string())) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct BlockUtxosV2Db(pub HashMap<UtxoIdV10, WalletScriptWithSourceAmountV1Db>); - -impl AsBytes for BlockUtxosV2Db { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(&bincode::serialize(&self).unwrap_or_else(|_| unreachable!())) - } -} - -impl kv_typed::prelude::FromBytes for BlockUtxosV2Db { - type Err = bincode::Error; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(bytes) - } -} - -impl ToDumpString for BlockUtxosV2Db { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for BlockUtxosV2Db { - fn from_explorer_str(_: &str) -> std::result::Result<Self, FromExplorerValueErr> { - unimplemented!() - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn utxo_val_v2() { - let amount = SourceAmount::with_base0(42); - let tx_hash = Hash::default(); - let output_index = 3; - let utxo_val = UtxoValV2::new(amount, tx_hash, output_index); - - assert_eq!(utxo_val.amount(), &amount); - assert_eq!(utxo_val.tx_hash(), &tx_hash); - assert_eq!(utxo_val.output_index(), output_index); - } -} diff --git a/rust-libs/duniter-dbs/src/values/wallet_db.rs b/rust-libs/duniter-dbs/src/values/wallet_db.rs deleted file mode 100644 index 465346100..000000000 --- a/rust-libs/duniter-dbs/src/values/wallet_db.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub struct WalletDbV1 { - pub conditions: String, - pub balance: u64, -} - -impl AsBytes for WalletDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let json = serde_json::to_string(self).unwrap_or_else(|_| unreachable!()); - f(json.as_bytes()) - } -} - -impl kv_typed::prelude::FromBytes for WalletDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let json_str = std::str::from_utf8(bytes).expect("corrupted db : invalid utf8 bytes"); - serde_json::from_str(&json_str) - .map_err(|e| CorruptedBytes(format!("{}: '{}'", e, json_str))) - } -} - -impl ToDumpString for WalletDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for WalletDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/src/values/wallet_script_with_sa.rs b/rust-libs/duniter-dbs/src/values/wallet_script_with_sa.rs deleted file mode 100644 index 5d40dd95a..000000000 --- a/rust-libs/duniter-dbs/src/values/wallet_script_with_sa.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct WalletScriptWithSourceAmountV1Db { - pub wallet_script: WalletScriptV10, - pub source_amount: SourceAmount, -} - -impl AsBytes for WalletScriptWithSourceAmountV1Db { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(&bincode::serialize(&self).unwrap_or_else(|_| unreachable!())) - } -} - -impl kv_typed::prelude::FromBytes for WalletScriptWithSourceAmountV1Db { - type Err = bincode::Error; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(bytes) - } -} - -impl ToDumpString for WalletScriptWithSourceAmountV1Db { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for WalletScriptWithSourceAmountV1Db { - fn from_explorer_str(_: &str) -> std::result::Result<Self, FromExplorerValueErr> { - unimplemented!() - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/duniter-dbs/tests/test_explorer.rs b/rust-libs/duniter-dbs/tests/test_explorer.rs deleted file mode 100644 index 2dabf7ef4..000000000 --- a/rust-libs/duniter-dbs/tests/test_explorer.rs +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#[cfg(feature = "explorer")] -mod explorer { - use dubp::common::crypto::keys::ed25519::PublicKey; - use dubp::common::crypto::keys::PublicKey as _; - //use dubp::common::prelude::*; - use duniter_dbs::kv_typed::prelude::*; - use duniter_dbs::kv_typed::regex; - use duniter_dbs::prelude::*; - use duniter_dbs::smallvec::smallvec; - use duniter_dbs::{ - databases::bc_v1::{BcV1Db, BcV1DbWritable}, - PublicKeySingletonDbV1, UidKeyV1, - }; - use std::{num::NonZeroUsize, str::FromStr}; - use tempfile::TempDir; - use unwrap::unwrap; - - const COLLECTION_NAME: &str = "uids"; - - fn stringify_json_value_test(v: serde_json::Value) -> serde_json::Value { - v - } - - #[test] - fn explorer_test_leveldb() -> anyhow::Result<()> { - let tmp_dir = unwrap!(TempDir::new()); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(tmp_dir.path().to_owned()))?; - - explorer_test(&db) - } - - #[test] - fn explorer_test_sled() -> anyhow::Result<()> { - let db = BcV1Db::<Sled>::open(SledConf::new().temporary(true))?; - - explorer_test(&db) - } - - fn explorer_test<B: Backend>(db: &BcV1Db<B>) -> anyhow::Result<()> { - // Defines test data - let k1 = unwrap!(UidKeyV1::from_str("toto")); - let k2 = unwrap!(UidKeyV1::from_str("titi")); - let v1 = PublicKeySingletonDbV1(unwrap!(PublicKey::from_base58( - "ByE9TU6qhktHYYVAqeTcWcaULBx151siQLyL3TrKvY85" - ))); - let v2 = PublicKeySingletonDbV1(unwrap!(PublicKey::from_base58( - "8B5XCAHknsckCkMWeGF9FoGibSNZXF9HtAvzxzg3bSyp" - ))); - - // Insert test data - db.uids_write().upsert(k1, v1)?; - db.uids_write().upsert(k2, v2)?; - - // Test action count - let res = db.explore( - COLLECTION_NAME, - ExplorerAction::Count, - stringify_json_value_test, - )??; - assert_eq!(ExplorerActionResponse::Count(2), res); - - // Test action get - let res = db.explore( - COLLECTION_NAME, - ExplorerAction::Get { key: "unexist" }, - stringify_json_value_test, - )??; - assert_eq!(ExplorerActionResponse::Get(None), res); - let res = db.explore( - COLLECTION_NAME, - ExplorerAction::Get { key: "toto" }, - stringify_json_value_test, - )??; - assert_eq!( - ExplorerActionResponse::Get(Some(serde_json::Value::String( - "ByE9TU6qhktHYYVAqeTcWcaULBx151siQLyL3TrKvY85".to_owned() - ))), - res - ); - - // Test action put - let res = db.explore( - COLLECTION_NAME, - ExplorerAction::Put { - key: "titu", - value: "Bi6ECSc352gdfEvVzGiQuuDQyaTptHkcxooMGTJk14Tr", - }, - stringify_json_value_test, - )??; - assert_eq!(ExplorerActionResponse::PutOk, res); - let res = db.explore( - COLLECTION_NAME, - ExplorerAction::Get { key: "titu" }, - stringify_json_value_test, - )??; - assert_eq!( - ExplorerActionResponse::Get(Some(serde_json::Value::String( - "Bi6ECSc352gdfEvVzGiQuuDQyaTptHkcxooMGTJk14Tr".to_owned() - ))), - res - ); - let res = db.explore( - COLLECTION_NAME, - ExplorerAction::Count, - stringify_json_value_test, - )??; - assert_eq!(ExplorerActionResponse::Count(3), res); - - // Test action find - let range_res = db.explore( - COLLECTION_NAME, - ExplorerAction::Find { - key_min: Some("ti00".to_owned()), - key_max: Some("tizz".to_owned()), - key_regex: None, - value_regex: None, - limit: Some(10), - reverse: false, - step: unsafe { NonZeroUsize::new_unchecked(1) }, - }, - stringify_json_value_test, - )??; - assert_eq!( - ExplorerActionResponse::Find(vec![ - EntryFound { - key: "titi".to_owned(), - value: serde_json::Value::String( - "8B5XCAHknsckCkMWeGF9FoGibSNZXF9HtAvzxzg3bSyp".to_owned() - ), - captures: None, - }, - EntryFound { - key: "titu".to_owned(), - value: serde_json::Value::String( - "Bi6ECSc352gdfEvVzGiQuuDQyaTptHkcxooMGTJk14Tr".to_owned() - ), - captures: None, - }, - ]), - range_res - ); - - // Test action find with limit - let range_res = db.explore( - COLLECTION_NAME, - ExplorerAction::Find { - key_min: Some("ti00".to_owned()), - key_max: Some("tizz".to_owned()), - key_regex: None, - value_regex: None, - limit: Some(1), - reverse: false, - step: unsafe { NonZeroUsize::new_unchecked(1) }, - }, - stringify_json_value_test, - )??; - assert_eq!( - ExplorerActionResponse::Find(vec![EntryFound { - key: "titi".to_owned(), - value: serde_json::Value::String( - "8B5XCAHknsckCkMWeGF9FoGibSNZXF9HtAvzxzg3bSyp".to_owned() - ), - captures: None, - }]), - range_res - ); - - // Test action find with limit and reverse - let range_res = db.explore( - COLLECTION_NAME, - ExplorerAction::Find { - key_min: Some("ti00".to_owned()), - key_max: Some("tizz".to_owned()), - key_regex: None, - value_regex: None, - limit: Some(1), - reverse: true, - step: unsafe { NonZeroUsize::new_unchecked(1) }, - }, - stringify_json_value_test, - )??; - assert_eq!( - ExplorerActionResponse::Find(vec![EntryFound { - key: "titu".to_owned(), - value: serde_json::Value::String( - "Bi6ECSc352gdfEvVzGiQuuDQyaTptHkcxooMGTJk14Tr".to_owned() - ), - captures: None, - }]), - range_res - ); - - // Test action find with regex capture - let range_res = db.explore( - COLLECTION_NAME, - ExplorerAction::Find { - key_min: Some("ti00".to_owned()), - key_max: Some("tizz".to_owned()), - key_regex: None, - value_regex: Some(regex::Regex::new("(E[Cv])[A-Z]").expect("wrong regex")), - limit: Some(10), - reverse: false, - step: unsafe { NonZeroUsize::new_unchecked(1) }, - }, - stringify_json_value_test, - )??; - assert_eq!( - ExplorerActionResponse::Find(vec![EntryFound { - key: "titu".to_owned(), - value: serde_json::Value::String( - "Bi6ECSc352gdfEvVzGiQuuDQyaTptHkcxooMGTJk14Tr".to_owned() - ), - captures: Some(ValueCaptures(smallvec![ - smallvec![Some("EC".to_owned())], - smallvec![Some("Ev".to_owned())] - ])), - }]), - range_res - ); - - // Test action delete - let res = db.explore( - COLLECTION_NAME, - ExplorerAction::Delete { key: "toto" }, - stringify_json_value_test, - )??; - assert_eq!(ExplorerActionResponse::DeleteOk, res); - let res = db.explore( - COLLECTION_NAME, - ExplorerAction::Get { key: "toto" }, - stringify_json_value_test, - )??; - assert_eq!(ExplorerActionResponse::Get(None), res); - - Ok(()) - } -} diff --git a/rust-libs/duniter-dbs/tests/test_read_write.rs b/rust-libs/duniter-dbs/tests/test_read_write.rs deleted file mode 100644 index d626b963a..000000000 --- a/rust-libs/duniter-dbs/tests/test_read_write.rs +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use dubp::common::crypto::keys::ed25519::PublicKey; -use dubp::common::crypto::keys::PublicKey as _; -use dubp::common::prelude::*; -use duniter_dbs::kv_typed::prelude::*; -use duniter_dbs::{ - databases::bc_v1::{BcV1Db, BcV1DbReadable, BcV1DbWritable, MainBlocksEvent}, - BlockDbV1, BlockNumberKeyV1, PublicKeySingletonDbV1, UidKeyV1, -}; -use kv_typed::channel::TryRecvError; -use std::str::FromStr; -use tempfile::TempDir; -use unwrap::unwrap; - -#[test] -fn write_read_delete_b0_leveldb() -> KvResult<()> { - let tmp_dir = unwrap!(TempDir::new()); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(tmp_dir.path().to_owned()))?; - - write_read_delete_b0_test(&db) -} - -#[test] -fn write_read_delete_b0_sled() -> KvResult<()> { - let db = BcV1Db::<Sled>::open(SledConf::new().temporary(true))?; - - write_read_delete_b0_test(&db) -} - -#[test] -fn iter_test_leveldb() -> KvResult<()> { - let tmp_dir = unwrap!(TempDir::new()); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(tmp_dir.path().to_owned()))?; - - write_some_entries_and_iter(&db) -} - -#[test] -fn iter_test_mem() -> KvResult<()> { - let db = BcV1Db::<Mem>::open(MemConf::default())?; - - write_some_entries_and_iter(&db) -} - -#[test] -fn iter_test_sled() -> KvResult<()> { - let db = BcV1Db::<Sled>::open(SledConf::new().temporary(true))?; - - write_some_entries_and_iter(&db) -} - -#[test] -fn batch_test_leveldb() -> KvResult<()> { - let tmp_dir = unwrap!(TempDir::new()); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(tmp_dir.path().to_owned()))?; - - batch_test(&db) -} - -#[test] -fn batch_test_mem() -> KvResult<()> { - let db = BcV1Db::<Mem>::open(MemConf::default())?; - - batch_test(&db) -} - -#[test] -fn batch_test_sled() -> KvResult<()> { - let db = BcV1Db::<Sled>::open(SledConf::new().temporary(true))?; - - batch_test(&db) -} - -fn write_read_delete_b0_test<B: Backend>(db: &BcV1Db<B>) -> KvResult<()> { - let main_blocks_reader = db.main_blocks(); - - let (subscriber, events_recv) = kv_typed::channel::unbounded(); - - main_blocks_reader.subscribe(subscriber)?; - - // Empty db - assert_eq!( - main_blocks_reader.get(&BlockNumberKeyV1(BlockNumber(0)))?, - None - ); - assert_eq!( - main_blocks_reader.get(&BlockNumberKeyV1(BlockNumber(1)))?, - None - ); - assert_eq!( - main_blocks_reader.iter(.., |iter| iter.keys().next_res())?, - None - ); - assert_eq!( - main_blocks_reader.iter(.., |iter| iter.values().next_res())?, - None - ); - if let Err(TryRecvError::Empty) = events_recv.try_recv() { - } else { - panic!("should not receive event"); - } - - // Insert b0 - let b0 = BlockDbV1::default(); - let main_blocks_writer = db.main_blocks_write(); - main_blocks_writer.upsert(BlockNumberKeyV1(BlockNumber(0)), b0.clone())?; - assert_eq!( - main_blocks_reader - .get(&BlockNumberKeyV1(BlockNumber(0)))? - .as_ref(), - Some(&b0) - ); - assert_eq!( - main_blocks_reader.get(&BlockNumberKeyV1(BlockNumber(1)))?, - None - ); - main_blocks_reader.iter(.., |iter| { - let mut keys_iter = iter.keys(); - assert_eq!( - keys_iter.next_res()?, - Some(BlockNumberKeyV1(BlockNumber(0))) - ); - assert_eq!(keys_iter.next_res()?, None); - Ok::<(), KvError>(()) - })?; - main_blocks_reader.iter(.., |iter| { - let mut values_iter = iter.values(); - assert_eq!(values_iter.next_res()?, Some(b0.clone())); - assert_eq!(values_iter.next_res()?, None); - - Ok::<(), KvError>(()) - })?; - if let Ok(events) = events_recv.try_recv() { - assert_eq!(events.len(), 1); - let event = &events[0]; - assert_eq!( - event, - &MainBlocksEvent::Upsert { - key: BlockNumberKeyV1(BlockNumber(0)), - value: b0, - }, - ); - } else { - panic!("should receive event"); - } - - // Delete b0 - main_blocks_writer.remove(BlockNumberKeyV1(BlockNumber(0)))?; - assert_eq!( - main_blocks_reader.get(&BlockNumberKeyV1(BlockNumber(0)))?, - None - ); - assert_eq!( - main_blocks_reader.get(&BlockNumberKeyV1(BlockNumber(1)))?, - None - ); - assert_eq!( - main_blocks_reader.iter(.., |it| it.keys().next_res())?, - None - ); - assert_eq!( - main_blocks_reader.iter(.., |it| it.values().next_res())?, - None - ); - if let Ok(events) = events_recv.try_recv() { - assert_eq!(events.len(), 1); - let event = &events[0]; - assert_eq!( - event, - &MainBlocksEvent::Remove { - key: BlockNumberKeyV1(BlockNumber(0)), - }, - ); - } else { - panic!("should receive event"); - } - - Ok(()) -} - -fn write_some_entries_and_iter<B: Backend>(db: &BcV1Db<B>) -> KvResult<()> { - let k1 = unwrap!(UidKeyV1::from_str("titi")); - let p1 = PublicKeySingletonDbV1(unwrap!(PublicKey::from_base58( - "42jMJtb8chXrpHMAMcreVdyPJK7LtWjEeRqkPw4eSEVp" - ))); - let k2 = unwrap!(UidKeyV1::from_str("titu")); - let p2 = PublicKeySingletonDbV1(unwrap!(PublicKey::from_base58( - "D7CYHJXjaH4j7zRdWngUbsURPnSnjsCYtvo6f8dvW3C" - ))); - let k3 = unwrap!(UidKeyV1::from_str("toto")); - let p3 = PublicKeySingletonDbV1(unwrap!(PublicKey::from_base58( - "8B5XCAHknsckCkMWeGF9FoGibSNZXF9HtAvzxzg3bSyp" - ))); - let uids_writer = db.uids_write(); - uids_writer.upsert(k1, p1)?; - uids_writer.upsert(k2, p2)?; - uids_writer.upsert(k3, p3)?; - - let uids_reader = db.uids(); - { - uids_reader.iter(.., |it| { - let mut values_iter_step_2 = it.values().step_by(2); - - assert_eq!(Some(p1), values_iter_step_2.next_res()?); - assert_eq!(Some(p3), values_iter_step_2.next_res()?); - assert_eq!(None, values_iter_step_2.next_res()?); - Ok::<(), KvError>(()) - })?; - - uids_reader.iter(.., |it| { - let mut entries_iter_step_2 = it.step_by(2); - - assert_eq!(Some((k1, p1)), entries_iter_step_2.next_res()?); - assert_eq!(Some((k3, p3)), entries_iter_step_2.next_res()?); - assert_eq!(None, entries_iter_step_2.next_res()?); - Ok::<(), KvError>(()) - })?; - - uids_reader.iter(k2.., |mut entries_iter| { - assert_eq!(Some((k2, p2)), entries_iter.next_res()?); - assert_eq!(Some((k3, p3)), entries_iter.next_res()?); - assert_eq!(None, entries_iter.next_res()?); - Ok::<(), KvError>(()) - })?; - - uids_reader.iter(..=k2, |mut entries_iter| { - assert_eq!(Some((k1, p1)), entries_iter.next_res()?); - assert_eq!(Some((k2, p2)), entries_iter.next_res()?); - assert_eq!(None, entries_iter.next_res()?); - Ok::<(), KvError>(()) - })?; - - uids_reader.iter_rev(k2.., |mut entries_iter_rev| { - assert_eq!(Some((k3, p3)), entries_iter_rev.next_res()?); - assert_eq!(Some((k2, p2)), entries_iter_rev.next_res()?); - assert_eq!(None, entries_iter_rev.next_res()?); - Ok::<(), KvError>(()) - })?; - - uids_reader.iter_rev(..=k2, |mut entries_iter_rev| { - assert_eq!(Some((k2, p2)), entries_iter_rev.next_res()?); - assert_eq!(Some((k1, p1)), entries_iter_rev.next_res()?); - Ok::<(), KvError>(()) - })?; - - uids_reader.iter_rev(..=k2, |iter_rev| { - let mut keys_iter_rev = iter_rev.keys(); - assert_eq!(Some(k2), keys_iter_rev.next_res()?); - assert_eq!(Some(k1), keys_iter_rev.next_res()?); - assert_eq!(None, keys_iter_rev.next_res()?); - Ok::<(), KvError>(()) - })?; - } - - uids_writer.remove(k3)?; - - uids_reader.iter(.., |it| { - let mut keys_iter = it.keys(); - - assert_eq!(Some(k1), keys_iter.next_res()?); - assert_eq!(Some(k2), keys_iter.next_res()?); - assert_eq!(None, keys_iter.next_res()?); - Ok::<(), KvError>(()) - })?; - - Ok(()) -} - -fn batch_test<B: Backend>(db: &BcV1Db<B>) -> KvResult<()> { - let main_blocks_reader = db.main_blocks(); - - let mut batch = db.new_batch(); - - let (subscriber, events_recv) = kv_typed::channel::unbounded(); - - main_blocks_reader.subscribe(subscriber)?; - - // Empty db - assert_eq!( - main_blocks_reader.get(&BlockNumberKeyV1(BlockNumber(0)))?, - None - ); - assert_eq!( - main_blocks_reader.get(&BlockNumberKeyV1(BlockNumber(1)))?, - None - ); - assert_eq!( - main_blocks_reader.iter(.., |it| it.keys().next_res())?, - None - ); - assert_eq!( - main_blocks_reader.iter(.., |it| it.values().next_res())?, - None - ); - if let Err(TryRecvError::Empty) = events_recv.try_recv() { - } else { - panic!("should not receive event"); - } - - // Insert b0 in batch - let b0 = BlockDbV1::default(); - batch - .main_blocks() - .upsert(BlockNumberKeyV1(BlockNumber(0)), b0.clone()); - - // bo should written in batch - assert_eq!( - batch.main_blocks().get(&BlockNumberKeyV1(BlockNumber(0))), - BatchGet::Updated(&b0) - ); - - // bo should not written in db - assert_eq!( - db.main_blocks().get(&BlockNumberKeyV1(BlockNumber(0)))?, - None - ); - - if let Err(TryRecvError::Empty) = events_recv.try_recv() { - } else { - panic!("should not receive event"); - } - - // Insert b1 in batch - let b1 = BlockDbV1 { - number: 1, - ..Default::default() - }; - batch - .main_blocks() - .upsert(BlockNumberKeyV1(BlockNumber(1)), b1.clone()); - - // Write batch in db - db.write_batch(batch)?; - - // bo should written in db - assert_eq!( - db.main_blocks() - .get(&BlockNumberKeyV1(BlockNumber(0)))? - .as_ref(), - Some(&b0) - ); - db.main_blocks().iter(.., |it| { - let mut keys_iter = it.keys(); - - assert_eq!( - keys_iter.next_res()?, - Some(BlockNumberKeyV1(BlockNumber(0))) - ); - assert_eq!( - keys_iter.next_res()?, - Some(BlockNumberKeyV1(BlockNumber(1))) - ); - assert_eq!(keys_iter.next_res()?, None); - Ok::<(), KvError>(()) - })?; - db.main_blocks().iter(.., |it| { - let mut values_iter = it.values(); - - assert_eq!(values_iter.next_res()?.as_ref(), Some(&b0)); - assert_eq!(values_iter.next_res()?.as_ref(), Some(&b1)); - assert_eq!(values_iter.next_res()?, None); - Ok::<(), KvError>(()) - })?; - if let Ok(events) = events_recv.try_recv() { - assert_eq!(events.len(), 2); - assert!(assert_eq_pairs( - [&events[0], &events[1]], - [ - &MainBlocksEvent::Upsert { - key: BlockNumberKeyV1(BlockNumber(0)), - value: b0, - }, - &MainBlocksEvent::Upsert { - key: BlockNumberKeyV1(BlockNumber(1)), - value: b1, - } - ] - )); - } else { - panic!("should receive event"); - } - - Ok(()) -} - -fn assert_eq_pairs<T: PartialEq>(a: [T; 2], b: [T; 2]) -> bool { - (a[0] == b[0] && a[1] == b[1]) || (a[1] == b[0] && a[0] == b[1]) -} diff --git a/rust-libs/duniter-dbs/tests/test_tmp_real.rs b/rust-libs/duniter-dbs/tests/test_tmp_real.rs deleted file mode 100644 index 563a71d03..000000000 --- a/rust-libs/duniter-dbs/tests/test_tmp_real.rs +++ /dev/null @@ -1,767 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -/*use dubp_common::crypto::bases::b58::ToBase58 as _; -use dubp_common::crypto::hashs::Hash; -use dubp_common::crypto::keys::PublicKey; -use dubp_common::prelude::*; -use duniter_dbs::kv_typed::prelude::*; -use duniter_dbs::*; -use duniter_dbs::{ - BcV1Db, BcV1DbReadable, BcV1DbWritable, BlockDbV1, BlockNumberKeyV1, PublicKeySingletonDbV1, - Result, UidKeyV1, -}; -use once_cell::sync::Lazy; -use std::{path::PathBuf, str::FromStr, sync::Mutex}; -use unwrap::unwrap; - -// Empty mutex used to ensure that only one test runs at a time -static MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(())); - -//const DB_PATH: &str = "/home/elois/.config/duniter/duniter_default/data"; -const DB_PATH: &str = "/home/elois/Documents/ml/leveldb-archives/g1-317499/leveldb"; - -#[test] -#[ignore] -fn db_v1_main_blocks__() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - //let block52 = db.get::<MainBlocksColV1>(&MainBlockKeyV1(52))?; - //println!("{:#?}", block52); - - let current_block_number_opt = db - .main_blocks() - .iter(..) - .keys() - .reverse() - .next() - .transpose()?; - if let Some(current_block_number) = current_block_number_opt { - println!("current_block_number={:#?}", current_block_number); - let current_block = db.main_blocks().get(¤t_block_number)?; - println!("current_block={:#?}", current_block); - } - - /*// Collect all main blocks - let entries = db - .main_blocks() - .iter(..) - .collect::<KvResult<Vec<(BlockNumberKeyV1, BlockDbV1)>>>()?; - println!("entries_len={}", entries.len());*/ - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_main_blocks_idty() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let all = unwrap!(db.mb_idty().get(&PubKeyKeyV1::all())?); - assert!(all.0.len() > 2); - - // Collect all main blocks idty - let entries = db - .mb_idty() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, BlockNumberArrayV1)>>>()?; - println!("identities_count={}", entries.len() - 1); - for (k, v) in &entries { - if v.0.len() == 2 { - println!("{:?}", k.0.as_ref()); - } - } - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_main_blocks_certs() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all main blocks idty - let entries = db - .mb_certs() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, BlockNumberArrayV1)>>>()?; - println!("certifications_count={}", entries.len() - 1); - for (k, v) in &entries[..10] { - if v.0.len() > 1 { - println!("{}={:?}", k.0, v.0); - } - } - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_main_blocks_joiners() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let all = unwrap!(db.mb_joiners().get(&PubKeyKeyV1::all())?); - assert!(all.0.len() > 100); - - // Collect all main blocks joiners - let entries = db - .mb_joiners() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, BlockNumberArrayV1)>>>()?; - println!("joiners_count={}", entries.len() - 1); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_main_blocks_actives() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let all = unwrap!(db.mb_actives().get(&PubKeyKeyV1::all())?); - assert!(all.0.len() > 100); - - // Collect all main blocks actives - let entries = db - .mb_actives() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, BlockNumberArrayV1)>>>()?; - println!("actives_count={}", entries.len() - 1); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_main_blocks_leavers() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let all = unwrap!(db.mb_leavers().get(&PubKeyKeyV1::all())?); - assert!(all.0.len() >= 3); - - // Collect all main blocks with leavers - let entries = db - .mb_leavers() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, BlockNumberArrayV1)>>>()?; - println!("leavers_count={}", entries.len() - 1); - for (k, v) in entries { - println!("{}={:?}", k.0, v.0); - } - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_main_blocks_excluded() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let all = unwrap!(db.mb_excluded().get(&PubKeyKeyV1::all())?); - assert!(all.0.len() >= 50); - - // Collect all main blocks with excluded - let entries = db - .mb_excluded() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, BlockNumberArrayV1)>>>()?; - println!("excluded_count={}", entries.len() - 1); - /*for (k, v) in entries { - println!("{}={:?}", k.0, v.0); - }*/ - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_main_blocks_revoked() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let all = unwrap!(db.mb_revoked().get(&PubKeyAndSigV1::all())?); - assert!(all.0.len() >= 20); - - // Collect all main blocks with revoked - let entries = db - .mb_revoked() - .iter(..) - .collect::<KvResult<Vec<(PubKeyAndSigV1, BlockNumberArrayV1)>>>()?; - println!("revoked_count={}", entries.len() - 1); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_main_blocks_dividend() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let all = unwrap!(db.mb_dividends().get(&AllKeyV1)?); - assert!(all.0.len() >= 900); - println!("blocks with dividend={}", all.0.len()); - println!("last block with dividend={:?}", all.0.last()); - - // Collect all main blocks with dividends - let entries = db - .mb_dividends() - .iter(..) - .collect::<KvResult<Vec<(AllKeyV1, BlockNumberArrayV1)>>>()?; - println!("dividends_keys={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_main_blocks_transactions() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let all = unwrap!(db.mb_transactions().get(&AllKeyV1)?); - assert!(all.0.len() >= 900); - println!("blocks with tx={}", all.0.len()); - println!("last block with tx={:?}", all.0.last()); - - // Collect all main blocks with transactions - let entries = db - .mb_transactions() - .iter(..) - .collect::<KvResult<Vec<(AllKeyV1, BlockNumberArrayV1)>>>()?; - println!("transactions_keys={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_fork_blocks() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - /*let fork_blocks_keys = db - .keys_iter::<ForkBlocksColV1, _>(..) - .take(1) - .collect::<KvResult<Vec<BlockstampKeyV1>>>()?; - let one_fork_block = unwrap!(db.get::<ForkBlocksColV1>(&fork_blocks_keys[0])?); - - println!("{:#?}", one_fork_block);*/ - - // Collect all fork blocks - let entries = db - .fork_blocks() - .iter(..) - .collect::<KvResult<Vec<(BlockstampKeyV1, BlockDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_bindex() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all bindex entries - let entries = db - .bindex() - .iter(..) - .collect::<KvResult<Vec<(BlockNumberKeyV1, BlockHeadDbV1)>>>()?; - println!("entries_len={}", entries.len()); - //println!("last_bindex={:?}", entries.last()); - //for (_k, v) in entries {} - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_iindex__() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let iindex_keys = db - .iindex() - .iter(..) - .keys() - .take(1) - .collect::<KvResult<Vec<PubKeyKeyV1>>>()?; - let one_iindex_db = unwrap!(db.iindex().get(&iindex_keys[0])?); - assert_eq!(one_iindex_db.0[0].pubkey, iindex_keys[0].0.to_base58()); - - //println!("{:#?}", one_iindex_db); - - if let Some(ref hash) = one_iindex_db.0[0].hash { - let pubkey = unwrap!(db - .iindex_hash() - .get(&HashKeyV1(unwrap!(Hash::from_hex(hash))))?); - assert_eq!(pubkey.0, iindex_keys[0].0); - } - - // Count iindex entries - let count = db.iindex().count()?; - println!("iindex size={}", count); - - // Count members - let count_members = db - .iindex() - .iter(..) - .filter_map(KvResult::ok) - .filter(|(_k, v)| v.0[0].member.is_some() && unwrap!(v.0[0].member)) - .count(); - println!("count_members={}", count_members); - - // Collect all iindex entries - let entries = db - .iindex() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, IIndexDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_iindex_hash() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let iindex_entries = db - .iindex_hash() - .iter(..) - .take(3) - .collect::<KvResult<Vec<(HashKeyV1, PublicKeySingletonDbV1)>>>()?; - - println!( - "(hash, pub)=({:#?},{:#?})", - iindex_entries[0].0, iindex_entries[0].1 - ); - - // Collect all iindex/hash entries - let entries = db - .iindex_hash() - .iter(..) - .collect::<KvResult<Vec<(HashKeyV1, PublicKeySingletonDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_iindex_kick() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let entries = db - .iindex_kick() - .iter(..) - .take(3) - .collect::<KvResult<Vec<(PubKeyKeyV1, KickDbV1)>>>()?; - - println!("(pub, kick)=({:#?},{:#?})", entries[0].0, entries[0].1); - - // Collect all iindex/kick entries - let entries = db - .iindex_kick() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, KickDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_iindex_written_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all iindex/written_on entries - let entries = db - .iindex_written_on() - .iter(..) - .collect::<KvResult<Vec<(BlockNumberKeyV1, PublicKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - println!("entries={:?}", entries); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_uid_col() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let uid_keys = db - .uids() - .iter(..) - .keys() - .take(1) - .collect::<KvResult<Vec<UidKeyV1>>>()?; - let one_pubkey_db = db.uids().get(&uid_keys[0])?; - - println!( - "(uid, pubkey) = ({}, {:#?})", - uid_keys[0].0.as_str(), - one_pubkey_db - ); - - let start_key = unwrap!(UidKeyV1::from_str("1b")); - let end_key = unwrap!(UidKeyV1::from_str("404_not_found")); - let uid_index = db - .uids() - .iter(start_key..end_key) - .collect::<KvResult<Vec<(UidKeyV1, PublicKeySingletonDbV1)>>>()?; - assert_eq!( - uid_index, - vec![( - unwrap!(UidKeyV1::from_str("1claude1")), - PublicKeySingletonDbV1(unwrap!(PublicKey::from_base58( - "8B5XCAHknsckCkMWeGF9FoGibSNZXF9HtAvzxzg3bSyp" - ))) - )], - ); - - // Collect all iindex/uid entries - let entries = db - .uids() - .iter(..) - .collect::<KvResult<Vec<(UidKeyV1, PublicKeySingletonDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_mindex__() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - let mindex_keys = db - .mindex() - .iter(..) - .keys() - .take(1) - .collect::<KvResult<Vec<PubKeyKeyV1>>>()?; - let one_mindex_db = unwrap!(db.mindex().get(&mindex_keys[0])?); - assert_eq!(one_mindex_db.0[0].pubkey, mindex_keys[0].0.to_base58()); - - //println!("{:#?}", one_mindex_db); - - // Count mindex entries - let count = db.mindex().count()?; - println!("mindex size={}", count); - - // Collect all mindex entries - let entries = db - .mindex() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, MIndexDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_mindex_expires_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all mindex/expires_on entries - let entries = db - .mindex_expires_on() - .iter(..) - .collect::<KvResult<Vec<(TimestampKeyV1, PublicKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - /*for (k, v) in entries { - if k.0 == BlockNumber(u32::MAX) { - println!("{:?}", v.0) - } - }*/ - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_mindex_revokes_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all mindex/revokes_on entries - let entries = db - .mindex_revokes_on() - .iter(..) - .collect::<KvResult<Vec<(TimestampKeyV1, PublicKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_mindex_written_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all mindex/written_on entries - let entries = db - .mindex_written_on() - .iter(..) - .collect::<KvResult<Vec<(BlockNumberKeyV1, PublicKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - for (k, v) in entries { - if k.0 == BlockNumber(u32::MAX) { - println!("{:?}", v.0) - } - } - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_cindex__() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all bindex entries - let entries = db - .cindex() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, CIndexDbV1)>>>()?; - println!("entries_len={}", entries.len()); - //println!("last_bindex={:?}", entries.last()); - for (_k, v) in entries { - for cindex_line in v.issued { - if cindex_line.created_on_ref.is_some() { - println!("cindex_line={:?}", cindex_line) - } - } - } - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_cindex_expires_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all cindex/expires_on entries - let entries = db - .cindex_expires_on() - .iter(..) - .collect::<KvResult<Vec<(BlockNumberKeyV1, PublicKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_cindex_written_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all cindex/written_on entries - let entries = db - .cindex_written_on() - .iter(..) - .collect::<KvResult<Vec<(BlockNumberKeyV1, PublicKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_wallet() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all wallet entries - let entries = db - .wallet() - .iter(..) - .collect::<KvResult<Vec<(WalletConditionsV1, WalletDbV1)>>>()?; - println!("entries_len={}", entries.len()); - let mut max_cond_len = 0; - for (k, _v) in entries { - if k.0.len() > max_cond_len { - max_cond_len = k.0.len(); - println!("k={}", k.0.as_str()); - } - } - println!("max_cond_len={}", max_cond_len); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_dividend() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all level_dividend entries - let entries = db - .uds() - .iter(..) - .collect::<KvResult<Vec<(PubKeyKeyV1, UdEntryDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - println!("entries[0]=({:?}, {:?})", entries[0].0, entries[0].1); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_dividend_written_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all level_dividend/level_dividend_trim_index entries - let entries = db - .uds_trim() - .iter(..) - .collect::<KvResult<Vec<(BlockNumberKeyV1, PublicKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_sindex() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all level_sindex entries - let entries = db - .sindex() - .iter(..) - .collect::<KvResult<Vec<(SourceKeyV1, SIndexDBV1)>>>()?; - println!("entries_len={}", entries.len()); - - println!("entries[0]=({:?}, {:?})", entries[0].0, entries[0].1); - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_sindex_written_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all mindex/written_on entries - let entries = db - .sindex_written_on() - .iter(..) - .collect::<KvResult<Vec<(BlockNumberKeyV1, SourceKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - for (k, v) in entries { - if k.0 == BlockNumber(u32::MAX) { - println!("{:?}", v.0) - } - } - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_sindex_consumed_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - // Collect all mindex/written_on entries - let entries = db - .sindex_consumed_on() - .iter(..) - .collect::<KvResult<Vec<(BlockNumberKeyV1, SourceKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - for (k, v) in entries { - println!("{:?} => {:?}", k.0, v.0) - } - - Ok(()) -} - -#[test] -#[ignore] -fn db_v1_sindex_conditions_on() -> Result<()> { - let _lock = MUTEX.lock().expect("MUTEX poisoned"); - - let db = BcV1Db::<LevelDb>::open(LevelDbConf::path(PathBuf::from(DB_PATH)))?; - - // Collect all mindex/written_on entries - let entries = db - .sindex_conditions() - .iter(..) - .collect::<KvResult<Vec<(WalletConditionsV1, SourceKeyArrayDbV1)>>>()?; - println!("entries_len={}", entries.len()); - /*for (k, v) in entries { - println!("{:?} => {:?}", k.0, v.0) - }*/ - - Ok(()) -}*/ diff --git a/rust-libs/duniter-global/Cargo.toml b/rust-libs/duniter-global/Cargo.toml deleted file mode 100644 index a67f4cda7..000000000 --- a/rust-libs/duniter-global/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "duniter-global" -version = "1.8.1" -authors = ["librelois <elois@duniter.org>"] -license = "AGPL-3.0" -edition = "2018" - -[dependencies] -async-rwlock = "1.3.0" -dubp = { version = "0.51.0", features = ["duniter"] } -duniter-dbs = { path = "../duniter-dbs" } -flume = "0.10" -mockall = { version = "0.9", optional = true } -once_cell = "1.5" -tokio = { version = "1.2", features = ["io-util", "rt-multi-thread"] } - -[features] -mock = ["mockall"] diff --git a/rust-libs/duniter-global/src/lib.rs b/rust-libs/duniter-global/src/lib.rs deleted file mode 100644 index ddfd94679..000000000 --- a/rust-libs/duniter-global/src/lib.rs +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -pub use tokio; - -use async_rwlock::RwLock; -use dubp::wallet::prelude::SourceAmount; -use duniter_dbs::BlockMetaV2; -use once_cell::sync::OnceCell; -use std::ops::Deref; - -pub static SELF_ENDPOINTS: RwLock<Option<Vec<String>>> = RwLock::new(None); - -static ASYNC_RUNTIME: OnceCell<tokio::runtime::Runtime> = OnceCell::new(); -static CURRENT_META: RwLock<Option<CurrentMeta>> = RwLock::new(None); -static SELF_PEER_OLD: RwLock<Option<duniter_dbs::PeerCardDbV1>> = RwLock::new(None); - -#[derive(Clone, Copy, Debug, Default)] -pub struct CurrentMeta { - pub current_ud: SourceAmount, - pub current_block_meta: BlockMetaV2, -} - -#[derive(Clone, Debug)] -pub enum GlobalBackGroundTaskMsg { - InitCurrentMeta(CurrentMeta), - NewCurrentBlock(BlockMetaV2), - GetSelfEndpoints(flume::Sender<Option<Vec<String>>>), - SetSelfPeerOld(duniter_dbs::PeerCardDbV1), -} - -pub async fn start_global_background_task(recv: flume::Receiver<GlobalBackGroundTaskMsg>) { - tokio::spawn(async move { - while let Ok(msg) = recv.recv_async().await { - match msg { - GlobalBackGroundTaskMsg::InitCurrentMeta(current_meta) => { - let mut write_guard = CURRENT_META.write().await; - write_guard.replace(current_meta); - } - GlobalBackGroundTaskMsg::NewCurrentBlock(current_block_meta) => { - let upgradable_read_guard = CURRENT_META.upgradable_read().await; - let new_current_meta = if let Some(dividend) = current_block_meta.dividend { - CurrentMeta { - current_ud: dividend, - current_block_meta, - } - } else if let Some(current_meta) = upgradable_read_guard.deref() { - CurrentMeta { - current_ud: current_meta.current_ud, - current_block_meta, - } - } else { - CurrentMeta { - current_ud: SourceAmount::ZERO, - current_block_meta, - } - }; - let mut write_guard = - async_rwlock::RwLockUpgradableReadGuard::upgrade(upgradable_read_guard) - .await; - write_guard.replace(new_current_meta); - } - GlobalBackGroundTaskMsg::GetSelfEndpoints(sender) => { - let read_guard = SELF_ENDPOINTS.read().await; - let _ = sender.send_async(read_guard.deref().clone()).await; - } - GlobalBackGroundTaskMsg::SetSelfPeerOld(self_peer_old) => { - let mut write_guard = SELF_PEER_OLD.write().await; - write_guard.replace(self_peer_old); - } - } - } - }); -} - -pub fn get_async_runtime() -> &'static tokio::runtime::Runtime { - ASYNC_RUNTIME.get_or_init(|| { - tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .expect("fail to build tokio runtime") - }) -} - -#[derive(Clone, Copy, Debug, Default)] -pub struct AsyncAccessor; - -impl AsyncAccessor { - pub fn new() -> Self { - AsyncAccessor - } - pub async fn get_current_meta<D: 'static, F: 'static + FnOnce(&CurrentMeta) -> D>( - &self, - f: F, - ) -> Option<D> { - let read_guard = CURRENT_META.read().await; - if let Some(current_meta) = read_guard.deref() { - Some(f(current_meta)) - } else { - None - } - } - pub async fn get_self_peer_old< - D: 'static, - F: 'static + FnOnce(&duniter_dbs::PeerCardDbV1) -> D, - >( - &self, - f: F, - ) -> Option<D> { - let read_guard = SELF_PEER_OLD.read().await; - if let Some(self_peer_old) = read_guard.deref() { - Some(f(self_peer_old)) - } else { - None - } - } -} - -#[cfg(feature = "mock")] -mockall::mock! { - pub AsyncAccessor { - pub async fn get_current_meta<D: 'static, F: 'static + FnOnce(&CurrentMeta) -> D>( - &self, - f: F, - ) -> Option<D>; - pub async fn get_self_peer_old< - D: 'static, - F: 'static + FnOnce(&duniter_dbs::PeerCardDbV1) -> D, - >( - &self, - f: F, - ) -> Option<D>; - } -} diff --git a/rust-libs/duniter-mempools/Cargo.toml b/rust-libs/duniter-mempools/Cargo.toml deleted file mode 100644 index 244f87ebc..000000000 --- a/rust-libs/duniter-mempools/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "duniter-mempools" -version = "0.1.0" -authors = ["elois <elois@duniter.org>"] -description = "Duniter mempools" -repository = "https://git.duniter.org/nodes/typescript/duniter" -keywords = ["dubp", "duniter", "blockchain", "mempool"] -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -dubp = { version = "0.51.0", features = ["duniter"] } -duniter-dbs = { path = "../duniter-dbs" } -duniter-bc-reader = { path = "../duniter-bc-reader" } -duniter-dbs-write-ops = { path = "../duniter-dbs-write-ops" } -log = "0.4.11" -thiserror = "1.0.20" - -[dev-dependencies] diff --git a/rust-libs/duniter-mempools/src/lib.rs b/rust-libs/duniter-mempools/src/lib.rs deleted file mode 100644 index 8a8870aae..000000000 --- a/rust-libs/duniter-mempools/src/lib.rs +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -use std::borrow::Cow; - -use dubp::common::crypto::keys::ed25519::PublicKey; -use dubp::documents::prelude::*; -use dubp::documents::transaction::TransactionDocumentV10; -use duniter_dbs::kv_typed::prelude::*; -use duniter_dbs::{ - databases::bc_v2::BcV2DbReadable, - databases::txs_mp_v2::{TxsMpV2Db, TxsMpV2DbReadable}, -}; -use thiserror::Error; - -#[derive(Clone, Copy, Debug, Default)] -pub struct Mempools { - pub txs: TxsMempool, -} - -#[derive(Debug, Error)] -pub enum TxMpError { - #[error("{0}")] - Db(KvError), - #[error("Mempool full")] - Full, - #[error("Transaction already written in blockchain")] - TxAlreadyWritten, -} - -impl From<KvError> for TxMpError { - fn from(e: KvError) -> Self { - TxMpError::Db(e) - } -} - -#[derive(Clone, Copy, Debug, Default)] -pub struct TxsMempool { - max_size: usize, -} - -impl TxsMempool { - pub fn new(max_size: usize) -> Self { - TxsMempool { max_size } - } - pub fn accept_new_tx<BcDb: BcV2DbReadable, TxsMpDb: TxsMpV2DbReadable>( - &self, - bc_db_ro: &BcDb, - server_pubkey: PublicKey, - tx: TransactionDocumentV10, - txs_mp_db_ro: &TxsMpDb, - ) -> Result<(), TxMpError> { - if duniter_bc_reader::tx_exist(bc_db_ro, tx.get_hash())? { - Err(TxMpError::TxAlreadyWritten) - } else if tx.issuers().contains(&server_pubkey) - || txs_mp_db_ro.txs().count()? < self.max_size - { - Ok(()) - } else { - Err(TxMpError::Full) - } - } - - pub fn add_pending_tx<B: Backend, BcDb: BcV2DbReadable>( - &self, - bc_db_ro: &BcDb, - server_pubkey: PublicKey, - txs_mp_db: &TxsMpV2Db<B>, - tx: &TransactionDocumentV10, - ) -> Result<(), TxMpError> { - if duniter_bc_reader::tx_exist(bc_db_ro, tx.get_hash())? { - Err(TxMpError::TxAlreadyWritten) - } else if tx.issuers().contains(&server_pubkey) { - duniter_dbs_write_ops::txs_mp::add_pending_tx( - |_, _| Ok(()), - txs_mp_db, - Cow::Borrowed(tx), - )?; - Ok(()) - } else { - duniter_dbs_write_ops::txs_mp::add_pending_tx( - |_tx, txs| { - if txs.count()? >= self.max_size { - Err(KvError::Custom(TxMpError::Full.into())) - } else { - Ok(()) - } - }, - txs_mp_db, - Cow::Borrowed(tx), - )?; - Ok(()) - } - } - - #[doc(hidden)] - pub fn add_pending_tx_force<B: Backend>( - &self, - txs_mp_db: &TxsMpV2Db<B>, - tx: &TransactionDocumentV10, - ) -> KvResult<()> { - duniter_dbs_write_ops::txs_mp::add_pending_tx(|_, _| Ok(()), txs_mp_db, Cow::Borrowed(tx))?; - Ok(()) - } - - pub fn get_free_rooms<TxsMpDb: TxsMpV2DbReadable>( - &self, - txs_mp_db_ro: &TxsMpDb, - ) -> KvResult<usize> { - Ok(self.max_size - txs_mp_db_ro.txs().count()?) - } -} diff --git a/rust-libs/duniter-module/Cargo.toml b/rust-libs/duniter-module/Cargo.toml deleted file mode 100644 index 9e1a43b99..000000000 --- a/rust-libs/duniter-module/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "duniter-module" -version = "0.1.0" -authors = ["librelois <elois@duniter.org>"] -license = "AGPL-3.0" -edition = "2018" - -[dependencies] -anyhow = "1.0.34" -async-trait = "0.1.41" -dubp = { version = "0.51.0", features = ["duniter"] } -duniter-conf = { path = "../duniter-conf" } -duniter-dbs = { path = "../duniter-dbs" } -duniter-global = { path = "../duniter-global" } -duniter-mempools = { path = "../duniter-mempools" } -fast-threadpool = "0.2.3" -log = "0.4" - -[dev-dependencies] -duniter-dbs = { path = "../duniter-dbs", features = ["mem"] } -paste = "1.0.2" -tokio = { version = "1.2", features = ["macros", "rt"] } diff --git a/rust-libs/duniter-module/src/lib.rs b/rust-libs/duniter-module/src/lib.rs deleted file mode 100644 index 79060eaba..000000000 --- a/rust-libs/duniter-module/src/lib.rs +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -use dubp::{ - block::DubpBlockV10, - common::prelude::{BlockNumber, Blockstamp}, - crypto::{hashs::Hash, keys::ed25519::PublicKey}, - documents::transaction::TransactionDocumentV10, -}; -use duniter_conf::{DuniterConf, DuniterMode}; -use duniter_dbs::{kv_typed::prelude::*, FileBackend, SharedDbs}; -use duniter_mempools::Mempools; -use std::path::Path; - -pub const SOFTWARE_NAME: &str = "duniter"; - -pub type Endpoint = String; - -#[async_trait::async_trait] -pub trait DuniterModule: 'static + Sized { - const INDEX_BLOCKS: bool = false; - - /// This function is called only if Self::INDEX_BLOCKS is true, - /// in this case it must be reimplemented because the default implementation panics. - fn apply_block( - _block: &DubpBlockV10, - _conf: &DuniterConf, - _profile_path_opt: Option<&Path>, - ) -> KvResult<()> { - unreachable!() - } - - /// This function is called only if Self::INDEX_BLOCKS is true, - /// in this case it must be reimplemented because the default implementation panics. - fn revert_block( - _block: &DubpBlockV10, - _conf: &DuniterConf, - _profile_path_opt: Option<&Path>, - ) -> KvResult<()> { - unreachable!() - } - - fn init( - conf: &DuniterConf, - currency: &str, - dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - mempools: Mempools, - mode: DuniterMode, - profile_path_opt: Option<&Path>, - software_version: &'static str, - ) -> anyhow::Result<(Self, Vec<Endpoint>)>; - - async fn start(self) -> anyhow::Result<()>; - - // Needed for BMA only, will be removed when the migration is complete. - #[doc(hidden)] - fn get_transactions_history_for_bma( - _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - _profile_path_opt: Option<&Path>, - _pubkey: PublicKey, - ) -> KvResult<Option<TxsHistoryForBma>> { - Ok(None) - } - // Needed for BMA only, will be removed when the migration is complete. - #[doc(hidden)] - fn get_tx_by_hash( - _dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - _hash: Hash, - _profile_path_opt: Option<&Path>, - ) -> KvResult<Option<(TransactionDocumentV10, Option<BlockNumber>)>> { - Ok(None) - } -} - -// Needed for BMA only, will be removed when the migration is complete. -#[doc(hidden)] -#[derive(Default)] -pub struct TxsHistoryForBma { - pub sent: Vec<(TransactionDocumentV10, Blockstamp, i64)>, - pub received: Vec<(TransactionDocumentV10, Blockstamp, i64)>, - pub sending: Vec<TransactionDocumentV10>, - pub pending: Vec<TransactionDocumentV10>, -} - -#[macro_export] -macro_rules! plug_duniter_modules { - ([$($M:ty),*], $TxsHistoryForBma:ident) => { - paste::paste! { - use anyhow::Context as _; - #[allow(dead_code)] - fn apply_block_modules( - block: Arc<DubpBlockV10>, - conf: Arc<duniter_conf::DuniterConf>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - profile_path_opt: Option<std::path::PathBuf>, - ) -> KvResult<()> { - $( - let [<$M:snake>] = if <$M>::INDEX_BLOCKS { - let block_arc_clone = Arc::clone(&block); - let conf_arc_clone = Arc::clone(&conf); - let profile_path_opt_clone = profile_path_opt.clone(); - Some(dbs_pool - .launch(move |_| <$M>::apply_block( - &block_arc_clone, - &conf_arc_clone, - profile_path_opt_clone.as_deref() - )) - .expect("thread pool disconnected")) - } else { - None - }; - )* - $( - if let Some(join_handle) = [<$M:snake>] { - join_handle.join().expect("thread pool disconnected")?; - } - )* - Ok(()) - } - #[allow(dead_code)] - fn apply_chunk_of_blocks_modules( - blocks: Arc<[DubpBlockV10]>, - conf: Arc<duniter_conf::DuniterConf>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - profile_path_opt: Option<std::path::PathBuf>, - ) -> KvResult<()> { - $( - let [<$M:snake>] = if <$M>::INDEX_BLOCKS { - let blocks_arc_clone = Arc::clone(&blocks); - let conf_arc_clone = Arc::clone(&conf); - let profile_path_opt_clone = profile_path_opt.clone(); - Some(dbs_pool - .launch(move |_| { - use std::ops::Deref as _; - for block in blocks_arc_clone.deref() { - <$M>::apply_block(&block, &conf_arc_clone, profile_path_opt_clone.as_deref())?; - } - Ok::<_, KvError>(()) - }) - .expect("thread pool disconnected")) - } else { - None - }; - )* - $( - if let Some(join_handle) = [<$M:snake>] { - join_handle.join().expect("thread pool disconnected")?; - } - )* - Ok(()) - } - #[allow(dead_code)] - fn revert_block_modules( - block: Arc<DubpBlockV10>, - conf: Arc<duniter_conf::DuniterConf>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - profile_path_opt: Option<std::path::PathBuf>, - ) -> KvResult<()> { - $( - let [<$M:snake>] = if <$M>::INDEX_BLOCKS { - let block_arc_clone = Arc::clone(&block); - let conf_arc_clone = Arc::clone(&conf); - let profile_path_opt_clone = profile_path_opt.clone(); - Some(dbs_pool - .launch(move |_| <$M>::revert_block( - &block_arc_clone, - &conf_arc_clone, - profile_path_opt_clone.as_deref() - )) - .expect("thread pool disconnected")) - } else { - None - }; - )* - $( - if let Some(join_handle) = [<$M:snake>] { - join_handle.join().expect("thread pool disconnected")?; - } - )* - Ok(()) - } - async fn start_duniter_modules( - conf: &DuniterConf, - currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - mempools: duniter_mempools::Mempools, - mode: DuniterMode, - profile_path_opt: Option<std::path::PathBuf>, - software_version: &'static str, - ) -> anyhow::Result<()> { - let mut all_endpoints = Vec::<String>::new(); - $( - let ([<$M:snake>], mut endpoints) =<$M>::init(conf, ¤cy, &dbs_pool, mempools, mode, profile_path_opt.as_deref(), software_version) - .with_context(|| format!("Fail to init module '{}'", stringify!($M)))?; - all_endpoints.append(&mut endpoints); - )* - - log::info!("TMP DEBUG SELF_ENDPOINTS={:?}", all_endpoints); - duniter_global::SELF_ENDPOINTS.write().await.replace(all_endpoints); - - $( - let [<$M:snake _handle>] = tokio::spawn([<$M:snake>].start()); - )* - - $( - [<$M:snake _handle>].await.map_err(|e| if e.is_cancelled() { - anyhow::Error::msg(format!("Module '{}' cancelled", stringify!($M))) - } else { - anyhow::Error::msg(format!("Module '{}' panic", stringify!($M))) - })? - .with_context(|| format!("Error on execution of module '{}'", stringify!($M)))?; - )* - - Ok(()) - } - - // Needed for BMA only, will be removed when the migration is complete. - #[allow(dead_code)] - #[doc(hidden)] - fn get_transactions_history_for_bma( - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - profile_path_opt: Option<&Path>, - pubkey: PublicKey, - ) -> KvResult<TxsHistoryForBma> { - $( - if let Some(txs_history) = <$M>::get_transactions_history_for_bma(dbs_pool, profile_path_opt, pubkey)? { - return Ok(txs_history); - } - )* - Ok(TxsHistoryForBma::default()) - } - // Needed for BMA only, will be removed when the migration is complete. - #[allow(dead_code)] - #[doc(hidden)] - fn get_tx_by_hash( - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - hash: Hash, - profile_path_opt: Option<&Path>, - ) -> KvResult<Option<(TransactionDocumentV10, Option<BlockNumber>)>> { - $( - if let Some(tx_with_wb) = <$M>::get_tx_by_hash(dbs_pool, hash, profile_path_opt)? { - return Ok(Some(tx_with_wb)); - } - )* - Ok(None) - } - } - }; -} - -#[cfg(test)] -mod tests { - use super::*; - use duniter_mempools::TxsMempool; - - struct TestMod1; - - #[async_trait::async_trait] - impl DuniterModule for TestMod1 { - fn init( - _conf: &DuniterConf, - _currency: &str, - _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - _mempools: Mempools, - _mode: DuniterMode, - profile_path_opt: Option<&Path>, - _software_version: &'static str, - ) -> anyhow::Result<(Self, Vec<Endpoint>)> { - if let Some(profile_path) = profile_path_opt { - let _file_path = profile_path.join("test_mod1.json"); - } - Ok((TestMod1, vec![])) - } - - async fn start(self) -> anyhow::Result<()> { - Ok(()) - } - } - - struct TestMod2; - - #[async_trait::async_trait] - impl DuniterModule for TestMod2 { - fn init( - _conf: &DuniterConf, - _currency: &str, - _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - _mempools: Mempools, - _mode: DuniterMode, - _profile_path_opt: Option<&Path>, - _software_version: &'static str, - ) -> anyhow::Result<(Self, Vec<Endpoint>)> { - Ok((TestMod2, vec![])) - } - - async fn start(self) -> anyhow::Result<()> { - Ok(()) - } - } - - #[tokio::test] - async fn test_macro_plug_duniter_modules() -> anyhow::Result<()> { - plug_duniter_modules!([TestMod1, TestMod2], TxsHistoryForBma); - - let dbs = SharedDbs::mem()?; - let threadpool = - fast_threadpool::ThreadPool::start(fast_threadpool::ThreadPoolConfig::default(), dbs); - - start_duniter_modules( - &DuniterConf::default(), - "test".to_owned(), - threadpool.into_async_handler(), - Mempools { - txs: TxsMempool::new(0), - }, - DuniterMode::Sync, - None, - "", - ) - .await?; - Ok(()) - } -} diff --git a/rust-libs/duniter-server/Cargo.toml b/rust-libs/duniter-server/Cargo.toml index 116a2d505..3cfbc9ed7 100644 --- a/rust-libs/duniter-server/Cargo.toml +++ b/rust-libs/duniter-server/Cargo.toml @@ -9,14 +9,8 @@ edition = "2018" anyhow = "1.0.34" cfg-if = "1.0.0" dubp = { version = "0.51.0", features = ["duniter"] } -duniter-conf = { path = "../duniter-conf" } -duniter-bc-reader = { path = "../duniter-bc-reader" } -duniter-dbs = { path = "../duniter-dbs" } -duniter-dbs-write-ops = { path = "../duniter-dbs-write-ops" } -duniter-global = { path = "../duniter-global" } -duniter-gva = { path = "../modules/gva", optional = true } -duniter-mempools = { path = "../duniter-mempools" } -duniter-module = { path = "../duniter-module" } +duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core", features = ["bc-writer"] } +duniter-gva = { git = "https://git.duniter.org/nodes/rust/modules/duniter-gva", optional = true } fast-threadpool = "0.2.3" flume = "0.10.0" log = "0.4.11" @@ -29,4 +23,4 @@ default = ["gva"] gva = ["duniter-gva"] [dev-dependencies] -duniter-dbs = { path = "../duniter-dbs", features = ["mem"] } +duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core", features = ["bc-writer", "mem"] } diff --git a/rust-libs/duniter-server/src/fill_cm.rs b/rust-libs/duniter-server/src/fill_cm.rs index 90b7aa96d..5251eafeb 100644 --- a/rust-libs/duniter-server/src/fill_cm.rs +++ b/rust-libs/duniter-server/src/fill_cm.rs @@ -15,8 +15,8 @@ use crate::*; use dubp::wallet::prelude::SourceAmount; -use duniter_dbs::databases::bc_v2::BcV2DbReadable; -use duniter_global::{CurrentMeta, GlobalBackGroundTaskMsg}; +use duniter_core::dbs::databases::bc_v2::BcV2DbReadable; +use duniter_core::global::{CurrentMeta, GlobalBackGroundTaskMsg}; pub(super) fn fill_and_get_current_meta<BcDb: BcV2DbReadable>( bc_db_ro: &BcDb, diff --git a/rust-libs/duniter-server/src/legacy/block_indexer.rs b/rust-libs/duniter-server/src/legacy/block_indexer.rs index a50a6ab0a..bf271807d 100644 --- a/rust-libs/duniter-server/src/legacy/block_indexer.rs +++ b/rust-libs/duniter-server/src/legacy/block_indexer.rs @@ -20,7 +20,7 @@ impl DuniterServer { let block = Arc::new( DubpBlockV10::from_string_object(&block).map_err(|e| KvError::DeserError(e.into()))?, ); - self.current = Some(duniter_dbs_write_ops::apply_block::apply_block( + self.current = Some(duniter_core::dbs_write_ops::apply_block::apply_block( &self.bc_db, block.clone(), self.current, @@ -39,7 +39,7 @@ impl DuniterServer { .collect::<Result<Vec<_>, _>>() .map_err(|e| KvError::DeserError(e.into()))?, ); - self.current = Some(duniter_dbs_write_ops::apply_block::apply_chunk( + self.current = Some(duniter_core::dbs_write_ops::apply_block::apply_chunk( &self.bc_db, self.current, &self.dbs_pool, @@ -56,13 +56,13 @@ impl DuniterServer { let txs_mp_job_handle = self .dbs_pool .launch(move |dbs| { - duniter_dbs_write_ops::txs_mp::revert_block( + duniter_core::dbs_write_ops::txs_mp::revert_block( block_arc_clone.transactions(), &dbs.txs_mp_db, ) }) .expect("dbs pool disconnected"); - self.current = duniter_dbs_write_ops::bc::revert_block(&self.bc_db, &block)?; + self.current = duniter_core::dbs_write_ops::bc::revert_block(&self.bc_db, &block)?; txs_mp_job_handle.join().expect("dbs pool disconnected")?; revert_block_modules(block, Arc::new(self.conf.clone()), &self.dbs_pool, None) } diff --git a/rust-libs/duniter-server/src/legacy/dunp.rs b/rust-libs/duniter-server/src/legacy/dunp.rs index e390f9e65..d153e53b8 100644 --- a/rust-libs/duniter-server/src/legacy/dunp.rs +++ b/rust-libs/duniter-server/src/legacy/dunp.rs @@ -18,7 +18,10 @@ use crate::*; impl DuniterServer { pub fn receive_new_heads( &self, - heads: Vec<(duniter_dbs::DunpNodeIdV1Db, duniter_dbs::DunpHeadDbV1)>, + heads: Vec<( + duniter_core::dbs::DunpNodeIdV1Db, + duniter_core::dbs::DunpHeadDbV1, + )>, ) -> KvResult<()> { self.dbs_pool .execute(move |dbs| { @@ -32,13 +35,13 @@ impl DuniterServer { .expect("dbs pool disconnected") } pub fn remove_all_peers(&self) -> KvResult<()> { - use duniter_dbs::databases::network_v1::NetworkV1DbWritable as _; + use duniter_core::dbs::databases::network_v1::NetworkV1DbWritable as _; self.dbs_pool .execute(move |dbs| dbs.dunp_db.peers_old_write().clear()) .expect("dbs pool disconnected") } pub fn remove_peer_by_pubkey(&self, pubkey: PublicKey) -> KvResult<()> { - use duniter_dbs::databases::network_v1::NetworkV1DbWritable as _; + use duniter_core::dbs::databases::network_v1::NetworkV1DbWritable as _; self.dbs_pool .execute(move |dbs| dbs.dunp_db.peers_old_write().remove(PubKeyKeyV2(pubkey))) .expect("dbs pool disconnected") @@ -46,12 +49,12 @@ impl DuniterServer { pub fn save_peer(&self, new_peer_card: PeerCardDbV1) -> anyhow::Result<()> { use dubp::crypto::keys::PublicKey as _; let pubkey = PublicKey::from_base58(&new_peer_card.pubkey)?; - use duniter_dbs::databases::network_v1::NetworkV1DbWritable as _; + use duniter_core::dbs::databases::network_v1::NetworkV1DbWritable as _; self.dbs_pool .execute(move |dbs| { dbs.dunp_db.peers_old_write().upsert( PubKeyKeyV2(pubkey), - duniter_dbs::PeerCardDbV1 { + duniter_core::dbs::PeerCardDbV1 { version: new_peer_card.version, currency: new_peer_card.currency, pubkey: new_peer_card.pubkey, @@ -78,8 +81,8 @@ mod tests { ed25519::{PublicKey, Signature}, PublicKey as _, }; - use duniter_dbs::databases::network_v1::NetworkV1DbReadable; - use duniter_dbs::PeerCardDbV1; + use duniter_core::dbs::databases::network_v1::NetworkV1DbReadable; + use duniter_core::dbs::PeerCardDbV1; use super::*; @@ -89,12 +92,12 @@ mod tests { let dbs = server.get_shared_dbs(); let head = ( - duniter_dbs::DunpNodeIdV1Db::new(53, PublicKey::default()), - duniter_dbs::DunpHeadDbV1 { + duniter_core::dbs::DunpNodeIdV1Db::new(53, PublicKey::default()), + duniter_core::dbs::DunpHeadDbV1 { api: "WS2P".to_owned(), pubkey: PublicKey::default(), blockstamp: Blockstamp::default(), - software: duniter_module::SOFTWARE_NAME.to_owned(), + software: duniter_core::module::SOFTWARE_NAME.to_owned(), software_version: "test".to_owned(), pow_prefix: 1, free_member_room: 0, @@ -113,7 +116,7 @@ mod tests { #[test] fn test_save_peer() -> anyhow::Result<()> { - use duniter_dbs::databases::network_v1::NetworkV1DbReadable as _; + use duniter_core::dbs::databases::network_v1::NetworkV1DbReadable as _; let server = DuniterServer::test(DuniterConf::default(), DuniterMode::Start)?; let dbs = server.get_shared_dbs(); diff --git a/rust-libs/duniter-server/src/legacy/txs_mempool.rs b/rust-libs/duniter-server/src/legacy/txs_mempool.rs index be7229fe4..3a484b9a2 100644 --- a/rust-libs/duniter-server/src/legacy/txs_mempool.rs +++ b/rust-libs/duniter-server/src/legacy/txs_mempool.rs @@ -69,10 +69,10 @@ impl DuniterServer { use std::ops::Deref as _; for event in events.deref() { match event { - duniter_dbs::databases::txs_mp_v2::TxsEvent::Upsert { key, value } => { + duniter_core::dbs::databases::txs_mp_v2::TxsEvent::Upsert { key, value } => { new_pending_txs.insert(key.0, value.0.clone()); } - duniter_dbs::databases::txs_mp_v2::TxsEvent::Remove { key } => { + duniter_core::dbs::databases::txs_mp_v2::TxsEvent::Remove { key } => { new_pending_txs.remove(&key.0); } _ => (), @@ -99,21 +99,21 @@ impl DuniterServer { pub fn remove_all_pending_txs(&self) -> KvResult<()> { self.dbs_pool .execute(move |dbs| { - duniter_dbs_write_ops::txs_mp::remove_all_pending_txs(&dbs.txs_mp_db) + duniter_core::dbs_write_ops::txs_mp::remove_all_pending_txs(&dbs.txs_mp_db) }) .expect("dbs pool disconnected") } pub fn remove_pending_tx_by_hash(&self, hash: Hash) -> KvResult<()> { self.dbs_pool .execute(move |dbs| { - duniter_dbs_write_ops::txs_mp::remove_pending_tx_by_hash(&dbs.txs_mp_db, hash) + duniter_core::dbs_write_ops::txs_mp::remove_pending_tx_by_hash(&dbs.txs_mp_db, hash) }) .expect("dbs pool disconnected") } pub fn trim_expired_non_written_txs(&self, limit_time: i64) -> KvResult<()> { self.dbs_pool .execute(move |dbs| { - duniter_dbs_write_ops::txs_mp::trim_expired_non_written_txs( + duniter_core::dbs_write_ops::txs_mp::trim_expired_non_written_txs( &dbs.txs_mp_db, limit_time, ) diff --git a/rust-libs/duniter-server/src/lib.rs b/rust-libs/duniter-server/src/lib.rs index 210932591..0dd1cb828 100644 --- a/rust-libs/duniter-server/src/lib.rs +++ b/rust-libs/duniter-server/src/lib.rs @@ -25,9 +25,9 @@ mod fill_cm; mod legacy; -pub use duniter_conf::{gva_conf::GvaConf, DuniterConf, DuniterMode}; -use duniter_dbs::databases::network_v1::NetworkV1DbWritable; -pub use duniter_dbs::{ +pub use duniter_core::conf::{gva_conf::GvaConf, DuniterConf, DuniterMode}; +use duniter_core::dbs::databases::network_v1::NetworkV1DbWritable; +pub use duniter_core::dbs::{ kv_typed::prelude::KvResult, smallvec, DunpHeadDbV1, DunpNodeIdV1Db, PeerCardDbV1, }; #[cfg(feature = "gva")] @@ -40,15 +40,15 @@ use dubp::documents::{prelude::*, transaction::TransactionDocumentV10}; use dubp::{ block::prelude::*, common::crypto::hashs::Hash, documents_parser::prelude::FromStringObject, }; -use duniter_dbs::{ +use duniter_core::dbs::{ databases::{bc_v2::BcV2Db, txs_mp_v2::TxsMpV2DbReadable}, kv_typed::prelude::*, PendingTxDbV2, PubKeyKeyV2, }; -use duniter_dbs::{prelude::*, BlockMetaV2, FileBackend}; -use duniter_global::{tokio, GlobalBackGroundTaskMsg}; -use duniter_mempools::{Mempools, TxMpError, TxsMempool}; -use duniter_module::{plug_duniter_modules, Endpoint, TxsHistoryForBma}; +use duniter_core::dbs::{prelude::*, BlockMetaV2, FileBackend}; +use duniter_core::global::{tokio, GlobalBackGroundTaskMsg}; +use duniter_core::mempools::{Mempools, TxMpError, TxsMempool}; +use duniter_core::module::{plug_duniter_modules, Endpoint, TxsHistoryForBma}; use fast_threadpool::ThreadPoolConfig; use resiter::{filter::Filter, map::Map}; use std::{ @@ -56,9 +56,13 @@ use std::{ path::{Path, PathBuf}, }; +// Plug duniter modules +use duniter_core::conf as duniter_conf; +use duniter_core::global as duniter_global; +use duniter_core::mempools as duniter_mempools; cfg_if::cfg_if! { if #[cfg(feature = "gva")] { - use duniter_module::DuniterModule as _; + use duniter_core::module::DuniterModule as _; plug_duniter_modules!([GvaModule], TxsHistoryForBma); } else { plug_duniter_modules!([], TxsHistoryForBma); @@ -72,7 +76,7 @@ pub struct DuniterServer { dbs_pool: fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, global_sender: flume::Sender<GlobalBackGroundTaskMsg>, pending_txs_subscriber: - flume::Receiver<Arc<Events<duniter_dbs::databases::txs_mp_v2::TxsEvent>>>, + flume::Receiver<Arc<Events<duniter_core::dbs::databases::txs_mp_v2::TxsEvent>>>, profile_path_opt: Option<PathBuf>, shared_dbs: SharedDbs<FileBackend>, txs_mempool: TxsMempool, @@ -94,7 +98,7 @@ impl DuniterServer { let txs_mempool = TxsMempool::new(conf.txs_mempool_size); log::info!("open duniter databases..."); - let (bc_db, shared_dbs) = duniter_dbs::open_dbs(profile_path_opt)?; + let (bc_db, shared_dbs) = duniter_core::dbs::open_dbs(profile_path_opt)?; shared_dbs.dunp_db.heads_old_write().clear()?; // Clear WS2Pv1 HEADs // Create channel with global async task @@ -127,9 +131,9 @@ impl DuniterServer { let profile_path_opt_clone = profile_path_opt.map(ToOwned::to_owned); let threadpool_async_handler = threadpool.async_handler(); std::thread::spawn(move || { - duniter_global::get_async_runtime().block_on(async { + duniter_core::global::get_async_runtime().block_on(async { // Start global background task - duniter_global::start_global_background_task(global_recv).await; + duniter_core::global::start_global_background_task(global_recv).await; // Start duniter modules if conf_clone.gva.is_some() { @@ -171,7 +175,7 @@ impl DuniterServer { "test".to_owned(), duniter_mode, None, - duniter_module::SOFTWARE_NAME, + duniter_core::module::SOFTWARE_NAME, ) } } diff --git a/rust-libs/modules/gva/Cargo.toml b/rust-libs/modules/gva/Cargo.toml deleted file mode 100644 index e5ed85962..000000000 --- a/rust-libs/modules/gva/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = "duniter-gva" -version = "0.1.0" -authors = ["librelois <elois@duniter.org>"] -license = "AGPL-3.0" -edition = "2018" - -[dependencies] -anyhow = "1.0.33" -arrayvec = "0.5.1" -async-graphql = "2.2.0" -async-mutex = "1.4.0" -async-trait = "0.1.41" -bytes = "1.0" -dubp = { version = "0.51.0", features = ["duniter"] } -duniter-bca = { path = "./bca" } -duniter-conf = { path = "../../duniter-conf" } -duniter-dbs = { path = "../../duniter-dbs" } -duniter-gva-db = { path = "./db" } -duniter-gva-dbs-reader = { path = "./dbs-reader" } -duniter-gva-indexer = { path = "./indexer" } -duniter-gva-gql = { path = "./gql" } -duniter-global = { path = "../../duniter-global" } -duniter-mempools = { path = "../../duniter-mempools" } -duniter-module = { path = "../../duniter-module" } -fast-threadpool = "0.2.3" -flume = "0.10.0" -futures = "0.3.6" -http = "0.2.1" -log = "0.4.11" -resiter = "0.4.0" -serde = { version = "1.0.105", features = ["derive"] } -serde_urlencoded = "0.7.0" -tokio = { version = "1.2", features = ["io-util", "rt-multi-thread"] } -warp = "0.3" - -[dev-dependencies] -duniter-dbs = { path = "../../duniter-dbs", features = ["mem"] } -mockall = "0.9.1" -serde_json = "1.0.53" -tokio = { version = "1.2", features = ["macros", "rt-multi-thread", "time"] } -unwrap = "1.2.1" diff --git a/rust-libs/modules/gva/bca/Cargo.toml b/rust-libs/modules/gva/bca/Cargo.toml deleted file mode 100644 index 4f3713c94..000000000 --- a/rust-libs/modules/gva/bca/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "duniter-bca" -version = "0.1.0" -authors = ["librelois <elois@duniter.org>"] -license = "AGPL-3.0" -edition = "2018" - -[dependencies] -anyhow = "1.0.33" -arrayvec = { version = "0.5.1", features = ["serde"] } -async-bincode = "0.6.1" -async_io_stream = { version = "0.3.1", features = [ "tokio_io"] } -bincode = "1.3" -dubp = { version = "0.51.0", features = ["duniter"] } -duniter-bca-types = { path = "types", features = ["duniter"] } -duniter-dbs = { path = "../../../duniter-dbs" } -duniter-gva-db = { path = "../db" } -duniter-gva-dbs-reader = { path = "../dbs-reader" } -duniter-global = { path = "../../../duniter-global" } -duniter-mempools = { path = "../../../duniter-mempools" } -fast-threadpool = "0.2.3" -futures = "0.3.6" -once_cell = "1.5" -smallvec = { version = "1.4.0", features = ["serde", "write"] } -tokio = { version = "1.2", features = ["macros", "rt-multi-thread"] } -uninit = "0.4.0" - -[dev-dependencies] -duniter-dbs = { path = "../../../duniter-dbs", features = ["mem"] } -duniter-gva-dbs-reader = { path = "../dbs-reader", features = ["mock"] } -duniter-global = { path = "../../../duniter-global", features = ["mock"] } -tokio = { version = "1.2", features = ["macros", "rt-multi-thread", "time"] } -mockall = "0.9.1" diff --git a/rust-libs/modules/gva/bca/src/exec_req_type.rs b/rust-libs/modules/gva/bca/src/exec_req_type.rs deleted file mode 100644 index 183a3e5e6..000000000 --- a/rust-libs/modules/gva/bca/src/exec_req_type.rs +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -mod balances; -mod current_ud; -mod last_blockstamp_out_of_fork_window; -mod members_count; -mod prepare_simple_payment; -mod send_txs; -mod utxos; - -use dubp::crypto::keys::KeyPair; - -use crate::*; - -#[derive(Debug, PartialEq)] -pub(super) struct ExecReqTypeError(pub(super) String); - -impl<E> From<E> for ExecReqTypeError -where - E: ToString, -{ - fn from(e: E) -> Self { - Self(e.to_string()) - } -} - -pub(super) async fn execute_req_type( - bca_executor: &BcaExecutor, - req_type: BcaReqTypeV0, - _is_whitelisted: bool, -) -> Result<BcaRespTypeV0, ExecReqTypeError> { - match req_type { - BcaReqTypeV0::BalancesOfPubkeys(pubkeys) => { - balances::exec_req_balances_of_pubkeys(bca_executor, pubkeys).await - } - BcaReqTypeV0::FirstUtxosOfPubkeys { - amount_target_opt, - pubkeys, - } => utxos::exec_req_first_utxos_of_pubkeys(bca_executor, amount_target_opt, pubkeys).await, - BcaReqTypeV0::LastBlockstampOutOfForkWindow => { - last_blockstamp_out_of_fork_window::exec_req_last_blockstamp_out_of_fork_window( - bca_executor, - ) - .await - } - BcaReqTypeV0::MembersCount => members_count::exec_req_members_count(bca_executor).await, - BcaReqTypeV0::PrepareSimplePayment(params) => { - prepare_simple_payment::exec_req_prepare_simple_payment(bca_executor, params).await - } - BcaReqTypeV0::ProofServerPubkey { challenge } => Ok(BcaRespTypeV0::ProofServerPubkey { - challenge, - server_pubkey: bca_executor.self_keypair.public_key(), - sig: bca_executor - .self_keypair - .generate_signator() - .sign(&challenge), - }), - BcaReqTypeV0::Ping => Ok(BcaRespTypeV0::Pong), - BcaReqTypeV0::SendTxs(txs) => send_txs::send_txs(bca_executor, txs).await, - BcaReqTypeV0::Identities(pubkeys) => { - let dbs_reader = bca_executor.dbs_reader(); - Ok(BcaRespTypeV0::Identities( - bca_executor - .dbs_pool - .execute(move |dbs| { - pubkeys - .into_iter() - .map(|pubkey| { - dbs_reader.idty(&dbs.bc_db_ro, pubkey).map(|idty_opt| { - idty_opt.map(|idty| Identity { - is_member: idty.is_member, - username: idty.username, - }) - }) - }) - .collect::<KvResult<ArrayVec<_>>>() - }) - .await??, - )) - } - BcaReqTypeV0::CurrentUd => current_ud::exec_req_current_ud(bca_executor).await, - BcaReqTypeV0::BalancesOfScripts(scripts) => { - balances::exec_req_balances_of_scripts(bca_executor, scripts).await - } - } -} diff --git a/rust-libs/modules/gva/bca/src/exec_req_type/balances.rs b/rust-libs/modules/gva/bca/src/exec_req_type/balances.rs deleted file mode 100644 index 6901a9d03..000000000 --- a/rust-libs/modules/gva/bca/src/exec_req_type/balances.rs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use dubp::{crypto::keys::ed25519::PublicKey, wallet::prelude::WalletScriptV10}; - -pub(super) async fn exec_req_balances_of_pubkeys( - bca_executor: &BcaExecutor, - pubkeys: ArrayVec<[PublicKey; 16]>, -) -> Result<BcaRespTypeV0, ExecReqTypeError> { - let dbs_reader = bca_executor.dbs_reader(); - Ok(BcaRespTypeV0::Balances( - bca_executor - .dbs_pool - .execute(move |_| { - pubkeys - .into_iter() - .map(|pubkey| { - dbs_reader - .get_account_balance(&WalletScriptV10::single_sig(pubkey)) - .map(|balance_opt| balance_opt.map(|balance| balance.0)) - }) - .collect::<Result<ArrayVec<_>, _>>() - }) - .await??, - )) -} - -pub(super) async fn exec_req_balances_of_scripts( - bca_executor: &BcaExecutor, - scripts: ArrayVec<[WalletScriptV10; 16]>, -) -> Result<BcaRespTypeV0, ExecReqTypeError> { - let dbs_reader = bca_executor.dbs_reader(); - Ok(BcaRespTypeV0::Balances( - bca_executor - .dbs_pool - .execute(move |_| { - scripts - .into_iter() - .map(|script| { - dbs_reader - .get_account_balance(&script) - .map(|balance_opt| balance_opt.map(|balance| balance.0)) - }) - .collect::<Result<ArrayVec<_>, _>>() - }) - .await??, - )) -} diff --git a/rust-libs/modules/gva/bca/src/exec_req_type/current_ud.rs b/rust-libs/modules/gva/bca/src/exec_req_type/current_ud.rs deleted file mode 100644 index 02823dbba..000000000 --- a/rust-libs/modules/gva/bca/src/exec_req_type/current_ud.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub(super) async fn exec_req_current_ud( - bca_executor: &BcaExecutor, -) -> Result<BcaRespTypeV0, ExecReqTypeError> { - if let Some(current_ud) = bca_executor - .cm_accessor - .get_current_meta(|cm| cm.current_ud) - .await - { - Ok(BcaRespTypeV0::CurrentUd(current_ud)) - } else { - Err("no blockchain".into()) - } -} diff --git a/rust-libs/modules/gva/bca/src/exec_req_type/last_blockstamp_out_of_fork_window.rs b/rust-libs/modules/gva/bca/src/exec_req_type/last_blockstamp_out_of_fork_window.rs deleted file mode 100644 index 41529563e..000000000 --- a/rust-libs/modules/gva/bca/src/exec_req_type/last_blockstamp_out_of_fork_window.rs +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use dubp::common::prelude::*; - -pub(super) async fn exec_req_last_blockstamp_out_of_fork_window( - bca_executor: &BcaExecutor, -) -> Result<BcaRespTypeV0, ExecReqTypeError> { - if let Some(current_block_number) = bca_executor - .cm_accessor - .get_current_meta(|cm| cm.current_block_meta.number) - .await - { - let dbs_reader = bca_executor.dbs_reader(); - bca_executor - .dbs_pool - .execute(move |dbs| { - let block_ref_number = if current_block_number < 101 { - 0 - } else { - current_block_number - 101 - }; - let block_ref_hash = dbs_reader - .block(&dbs.bc_db_ro, U32BE(block_ref_number))? - .expect("unreachable") - .hash; - Ok::<_, ExecReqTypeError>(BcaRespTypeV0::LastBlockstampOutOfForkWindow( - Blockstamp { - number: BlockNumber(block_ref_number), - hash: BlockHash(block_ref_hash), - }, - )) - }) - .await? - } else { - Err("no blockchain".into()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::*; - - #[tokio::test] - async fn test_exec_req_last_blockstamp_out_of_fork_window_no_blockchain() { - let mut cm_mock = MockAsyncAccessor::new(); - cm_mock - .expect_get_current_meta::<u32>() - .times(1) - .returning(|_| None); - let dbs_reader = MockDbsReader::new(); - let bca_executor = - create_bca_executor(cm_mock, dbs_reader).expect("fail to create bca executor"); - - let resp_res = exec_req_last_blockstamp_out_of_fork_window(&bca_executor).await; - - assert_eq!(resp_res, Err(ExecReqTypeError("no blockchain".into()))); - } - - #[tokio::test] - async fn test_exec_req_last_blockstamp_out_of_fork_window_ok() -> Result<(), ExecReqTypeError> { - let mut cm_mock = MockAsyncAccessor::new(); - cm_mock - .expect_get_current_meta::<u32>() - .times(1) - .returning(|f| Some(f(&CurrentMeta::default()))); - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_block() - .times(1) - .returning(|_, _| Ok(Some(BlockMetaV2::default()))); - - let bca_executor = - create_bca_executor(cm_mock, dbs_reader).expect("fail to create bca executor"); - - let resp = exec_req_last_blockstamp_out_of_fork_window(&bca_executor).await?; - - assert_eq!( - resp, - BcaRespTypeV0::LastBlockstampOutOfForkWindow(Blockstamp::default()) - ); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/bca/src/exec_req_type/members_count.rs b/rust-libs/modules/gva/bca/src/exec_req_type/members_count.rs deleted file mode 100644 index 71b85c6e3..000000000 --- a/rust-libs/modules/gva/bca/src/exec_req_type/members_count.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub(super) async fn exec_req_members_count( - bca_executor: &BcaExecutor, -) -> Result<BcaRespTypeV0, ExecReqTypeError> { - if let Some(members_count) = bca_executor - .cm_accessor - .get_current_meta(|cm| cm.current_block_meta.members_count) - .await - { - Ok(BcaRespTypeV0::MembersCount(members_count)) - } else { - Err("no blockchain".into()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::*; - - #[tokio::test] - async fn test_exec_req_members_count() { - let mut cm_mock = MockAsyncAccessor::new(); - cm_mock - .expect_get_current_meta::<u64>() - .times(1) - .returning(|f| Some(f(&CurrentMeta::default()))); - let dbs_reader = MockDbsReader::new(); - let bca_executor = - create_bca_executor(cm_mock, dbs_reader).expect("fail to create bca executor"); - - let resp_res = exec_req_members_count(&bca_executor).await; - - assert_eq!(resp_res, Ok(BcaRespTypeV0::MembersCount(0))); - } -} diff --git a/rust-libs/modules/gva/bca/src/exec_req_type/prepare_simple_payment.rs b/rust-libs/modules/gva/bca/src/exec_req_type/prepare_simple_payment.rs deleted file mode 100644 index a23a77650..000000000 --- a/rust-libs/modules/gva/bca/src/exec_req_type/prepare_simple_payment.rs +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software current_block_number: (), current_block_hash: (), inputs: (), inputs_sum: (): you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use dubp::wallet::prelude::*; -use duniter_bca_types::prepare_payment::{PrepareSimplePayment, PrepareSimplePaymentResp}; - -pub(super) async fn exec_req_prepare_simple_payment( - bca_executor: &BcaExecutor, - params: PrepareSimplePayment, -) -> Result<BcaRespTypeV0, ExecReqTypeError> { - let issuer = params.issuer; - - if let Some(current_meta) = bca_executor.cm_accessor.get_current_meta(|cm| *cm).await { - let current_block_meta = current_meta.current_block_meta; - let current_ud = current_meta.current_ud; - let dbs_reader = bca_executor.dbs_reader(); - let (amount, block_ref_number, block_ref_hash, (inputs, inputs_sum)) = bca_executor - .dbs_pool - .execute(move |dbs| { - let mut amount = params.amount.to_cents(current_ud); - let block_ref_number = if current_block_meta.number < 101 { - 0 - } else { - current_block_meta.number - 101 - }; - let block_ref_hash = dbs_reader - .block(&dbs.bc_db_ro, U32BE(block_ref_number))? - .expect("unreachable") - .hash; - let current_base = current_block_meta.unit_base as i64; - - if amount.base() > current_base { - Err("too long base".into()) - } else { - while amount.base() < current_base { - amount = amount.increment_base(); - } - Ok::<_, ExecReqTypeError>(( - amount, - block_ref_number, - block_ref_hash, - dbs_reader.find_inputs( - &dbs.bc_db_ro, - &dbs.txs_mp_db, - amount, - &WalletScriptV10::single(WalletConditionV10::Sig(issuer)), - false, - )?, - )) - } - }) - .await??; - - if inputs_sum < amount { - return Err("insufficient balance".into()); - } - - Ok(BcaRespTypeV0::PrepareSimplePayment( - PrepareSimplePaymentResp { - current_block_number: block_ref_number, - current_block_hash: block_ref_hash, - current_ud, - inputs, - inputs_sum, - }, - )) - } else { - Err("no blockchain".into()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::*; - - #[tokio::test] - async fn test_exec_req_prepare_simple_payment_no_blockchain() { - let mut mock_cm = MockAsyncAccessor::new(); - mock_cm - .expect_get_current_meta::<CurrentMeta>() - .times(1) - .returning(|_| None); - let dbs_reader = MockDbsReader::new(); - let bca_executor = - create_bca_executor(mock_cm, dbs_reader).expect("fail to create bca executor"); - - let resp_res = exec_req_prepare_simple_payment( - &bca_executor, - PrepareSimplePayment { - issuer: PublicKey::default(), - amount: Amount::Cents(SourceAmount::new(42, 0)), - }, - ) - .await; - - assert_eq!(resp_res, Err(ExecReqTypeError("no blockchain".into()))); - } - - #[tokio::test] - async fn test_exec_req_prepare_simple_payment_too_long_base() { - let mut mock_cm = MockAsyncAccessor::new(); - mock_cm - .expect_get_current_meta::<CurrentMeta>() - .times(1) - .returning(|f| Some(f(&CurrentMeta::default()))); - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_block() - .times(1) - .returning(|_, _| Ok(Some(BlockMetaV2::default()))); - let bca_executor = - create_bca_executor(mock_cm, dbs_reader).expect("fail to create bca executor"); - - let resp_res = exec_req_prepare_simple_payment( - &bca_executor, - PrepareSimplePayment { - issuer: PublicKey::default(), - amount: Amount::Cents(SourceAmount::new(42, 1)), - }, - ) - .await; - - assert_eq!(resp_res, Err(ExecReqTypeError("too long base".into()))); - } - - #[tokio::test] - async fn test_exec_req_prepare_simple_payment_insufficient_balance() { - let mut mock_cm = MockAsyncAccessor::new(); - mock_cm - .expect_get_current_meta::<CurrentMeta>() - .times(1) - .returning(|f| Some(f(&CurrentMeta::default()))); - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_block() - .times(1) - .returning(|_, _| Ok(Some(BlockMetaV2::default()))); - dbs_reader - .expect_find_inputs::<TxsMpV2Db<FileBackend>>() - .times(1) - .returning(|_, _, _, _, _| Ok((vec![], SourceAmount::default()))); - let bca_executor = - create_bca_executor(mock_cm, dbs_reader).expect("fail to create bca executor"); - - let resp_res = exec_req_prepare_simple_payment( - &bca_executor, - PrepareSimplePayment { - issuer: PublicKey::default(), - amount: Amount::Cents(SourceAmount::new(42, 0)), - }, - ) - .await; - - assert_eq!( - resp_res, - Err(ExecReqTypeError("insufficient balance".into())) - ); - } - - #[tokio::test] - async fn test_exec_req_prepare_simple_payment_ok() -> Result<(), ExecReqTypeError> { - let input = TransactionInputV10 { - amount: SourceAmount::with_base0(57), - id: SourceIdV10::Utxo(UtxoIdV10 { - tx_hash: Hash::default(), - output_index: 3, - }), - }; - - let mut mock_cm = MockAsyncAccessor::new(); - mock_cm - .expect_get_current_meta::<CurrentMeta>() - .times(1) - .returning(|f| Some(f(&CurrentMeta::default()))); - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_block() - .times(1) - .returning(|_, _| Ok(Some(BlockMetaV2::default()))); - dbs_reader - .expect_find_inputs::<TxsMpV2Db<FileBackend>>() - .times(1) - .returning(move |_, _, _, _, _| Ok((vec![input], SourceAmount::with_base0(57)))); - let bca_executor = - create_bca_executor(mock_cm, dbs_reader).expect("fail to create bca executor"); - - let resp = exec_req_prepare_simple_payment( - &bca_executor, - PrepareSimplePayment { - issuer: PublicKey::default(), - amount: Amount::Cents(SourceAmount::new(42, 0)), - }, - ) - .await?; - - assert_eq!( - resp, - BcaRespTypeV0::PrepareSimplePayment(PrepareSimplePaymentResp { - current_block_number: 0, - current_block_hash: Hash::default(), - current_ud: SourceAmount::ZERO, - inputs: vec![input], - inputs_sum: SourceAmount::with_base0(57), - }) - ); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/bca/src/exec_req_type/send_txs.rs b/rust-libs/modules/gva/bca/src/exec_req_type/send_txs.rs deleted file mode 100644 index e6a5c25c4..000000000 --- a/rust-libs/modules/gva/bca/src/exec_req_type/send_txs.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use dubp::{crypto::keys::KeyPair, documents::transaction::TransactionDocumentTrait}; -use duniter_bca_types::{ - rejected_tx::{RejectedTx, RejectedTxReason}, - Txs, -}; - -pub(super) async fn send_txs( - bca_executor: &BcaExecutor, - txs: Txs, -) -> Result<BcaRespTypeV0, ExecReqTypeError> { - let expected_currency = bca_executor.currency.clone(); - - let server_pubkey = bca_executor.self_keypair.public_key(); - let txs_mempool = bca_executor.txs_mempool; - - let mut rejected_txs = Vec::new(); - for (i, tx) in txs.into_iter().enumerate() { - if let Err(e) = tx.verify(Some(&expected_currency)) { - rejected_txs.push(RejectedTx { - tx_index: i as u16, - reason: RejectedTxReason::InvalidTx(e.to_string()), - }); - } else if let Err(rejected_tx) = bca_executor - .dbs_pool - .execute(move |dbs| { - txs_mempool - .add_pending_tx(&dbs.bc_db_ro, server_pubkey, &dbs.txs_mp_db, &tx) - .map_err(|e| RejectedTx { - tx_index: i as u16, - reason: match e { - duniter_mempools::TxMpError::Db(e) => { - RejectedTxReason::DbError(e.to_string()) - } - duniter_mempools::TxMpError::Full => RejectedTxReason::MempoolFull, - duniter_mempools::TxMpError::TxAlreadyWritten => { - RejectedTxReason::TxAlreadyWritten - } - }, - }) - }) - .await? - { - rejected_txs.push(rejected_tx); - } - } - Ok(BcaRespTypeV0::RejectedTxs(rejected_txs)) -} diff --git a/rust-libs/modules/gva/bca/src/exec_req_type/utxos.rs b/rust-libs/modules/gva/bca/src/exec_req_type/utxos.rs deleted file mode 100644 index 249ff1f48..000000000 --- a/rust-libs/modules/gva/bca/src/exec_req_type/utxos.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use dubp::{crypto::keys::ed25519::PublicKey, wallet::prelude::WalletScriptV10}; - -pub(super) async fn exec_req_first_utxos_of_pubkeys( - bca_executor: &BcaExecutor, - amount_target_opt: Option<Amount>, - pubkeys: ArrayVec<[PublicKey; 16]>, -) -> Result<BcaRespTypeV0, ExecReqTypeError> { - if let Some(current_ud) = bca_executor - .cm_accessor - .get_current_meta(|cm| cm.current_ud) - .await - { - let dbs_reader = bca_executor.dbs_reader(); - let scripts: ArrayVec<[WalletScriptV10; 16]> = pubkeys - .into_iter() - .map(WalletScriptV10::single_sig) - .collect(); - if let Some(amount_target) = amount_target_opt { - Ok(BcaRespTypeV0::FirstUtxosOfPubkeys( - bca_executor - .dbs_pool - .execute(move |_| { - Ok::<_, ExecReqTypeError>(dbs_reader.first_scripts_utxos( - Some(amount_target.to_cents(current_ud)), - 40, - &scripts, - )?) - }) - .await??, - )) - } else { - Ok(BcaRespTypeV0::FirstUtxosOfPubkeys( - bca_executor - .dbs_pool - .execute(move |_| dbs_reader.first_scripts_utxos(None, 40, &scripts)) - .await??, - )) - } - } else { - Err("no blockchain".into()) - } -} diff --git a/rust-libs/modules/gva/bca/src/lib.rs b/rust-libs/modules/gva/bca/src/lib.rs deleted file mode 100644 index 0ac1a1c9f..000000000 --- a/rust-libs/modules/gva/bca/src/lib.rs +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright (C) 2020 Éloïs req_id: (), resp_type: ()SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -mod exec_req_type; - -const MAX_BATCH_SIZE: usize = 10; -const RESP_MIN_SIZE: usize = 64; -type RespBytes = SmallVec<[u8; RESP_MIN_SIZE]>; - -use crate::exec_req_type::ExecReqTypeError; -#[cfg(test)] -use crate::tests::AsyncAccessor; -use arrayvec::ArrayVec; -use async_bincode::AsyncBincodeReader; -use async_io_stream::IoStream; -use bincode::Options as _; -use dubp::crypto::keys::{ed25519::Ed25519KeyPair, Signator}; -use duniter_bca_types::{ - amount::Amount, bincode_opts, identity::Identity, BcaReq, BcaReqExecError, BcaReqTypeV0, - BcaResp, BcaRespTypeV0, BcaRespV0, -}; -pub use duniter_dbs::kv_typed::prelude::*; -use duniter_dbs::{FileBackend, SharedDbs}; -#[cfg(not(test))] -use duniter_global::AsyncAccessor; -use duniter_gva_dbs_reader::DbsReader; - -use futures::{prelude::stream::FuturesUnordered, StreamExt, TryStream, TryStreamExt}; -use once_cell::sync::OnceCell; -use smallvec::SmallVec; -use tokio::task::JoinError; - -#[cfg(test)] -use crate::tests::DbsReaderImpl; -#[cfg(not(test))] -use duniter_gva_dbs_reader::DbsReaderImpl; - -static BCA_EXECUTOR: OnceCell<BcaExecutor> = OnceCell::new(); - -pub fn set_bca_executor( - currency: String, - cm_accessor: AsyncAccessor, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - dbs_reader: DbsReaderImpl, - self_keypair: Ed25519KeyPair, - software_version: &'static str, - txs_mempool: duniter_mempools::TxsMempool, -) { - BCA_EXECUTOR - .set(BcaExecutor { - currency, - cm_accessor, - dbs_pool, - dbs_reader, - self_keypair, - software_version, - txs_mempool, - }) - .unwrap_or_else(|_| panic!("BCA_EXECUTOR already set !")) -} - -#[cfg(not(test))] -pub async fn execute<B, S>(query_body_stream: S, is_whitelisted: bool) -> Vec<u8> -where - B: AsRef<[u8]>, - S: 'static + TryStream<Ok = B, Error = std::io::Error> + Send + Unpin, -{ - unsafe { - BCA_EXECUTOR - .get_unchecked() - .execute(query_body_stream, is_whitelisted) - .await - } -} - -#[derive(Clone)] -struct BcaExecutor { - cm_accessor: AsyncAccessor, - currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - dbs_reader: DbsReaderImpl, - self_keypair: Ed25519KeyPair, - software_version: &'static str, - txs_mempool: duniter_mempools::TxsMempool, -} -use uninit::extension_traits::VecCapacity; -impl BcaExecutor { - pub async fn execute<B, S>(&self, query_body_stream: S, is_whitelisted: bool) -> Vec<u8> - where - B: AsRef<[u8]>, - S: 'static + TryStream<Ok = B, Error = std::io::Error> + Send + Unpin, - { - let async_bincode_reader = - AsyncBincodeReader::<IoStream<S, B>, BcaReq>::from(IoStream::new(query_body_stream)); - self.execute_inner(async_bincode_reader, is_whitelisted) - .await - .into_iter() - .fold(Vec::new(), |mut vec, elem| { - // Write resp len - let out = vec.reserve_uninit(4); - out.copy_from_slice(&u32::to_be_bytes(elem.len() as u32)[..]); - unsafe { - // # Safety - // - // - `.copy_from_slice()` contract guarantees initialization - // of `out`, which, in turn, from `reserve_uninit`'s contract, - // leads to the `vec` extra capacity having been initialized. - vec.set_len(vec.len() + 4); - } - - // Write resp content - let out = vec.reserve_uninit(elem.len()); - out.copy_from_slice(&elem[..]); - unsafe { - // # Safety - // - // - `.copy_from_slice()` contract guarantees initialization - // of `out`, which, in turn, from `reserve_uninit`'s contract, - // leads to the `vec` extra capacity having been initialized. - vec.set_len(vec.len() + elem.len()); - } - vec - }) - } - - async fn execute_inner( - &self, - stream: impl TryStream<Ok = BcaReq, Error = bincode::Error>, - is_whitelisted: bool, - ) -> Vec<RespBytes> { - match stream - .map_ok(|req| { - let self_clone = self.clone(); - tokio::spawn(async move { self_clone.execute_req(req, is_whitelisted).await }) - }) - .take(MAX_BATCH_SIZE) - .try_collect::<FuturesUnordered<_>>() - .await - { - Ok(futures_unordered) => { - futures_unordered - .map(|req_res: Result<BcaResp, JoinError>| { - let resp = match req_res { - Ok(resp) => Ok(resp), - Err(e) => Err(if e.is_cancelled() { - BcaReqExecError::Cancelled - } else if e.is_panic() { - BcaReqExecError::Panic - } else { - BcaReqExecError::Unknown - }), - }; - let mut resp_buffer = RespBytes::new(); - bincode_opts() - .serialize_into(&mut resp_buffer, &resp) - .expect("unreachable"); - resp_buffer - }) - .collect() - .await - } - Err(e) => { - let req_res: Result<BcaResp, BcaReqExecError> = - Err(BcaReqExecError::InvalidReq(e.to_string())); - let mut resp_buffer = RespBytes::new(); - bincode_opts() - .serialize_into(&mut resp_buffer, &req_res) - .expect("unreachable"); - vec![resp_buffer] - } - } - } - - #[inline(always)] - async fn execute_req(self, req: BcaReq, is_whitelisted: bool) -> BcaResp { - match req { - BcaReq::V0(req) => BcaResp::V0(BcaRespV0 { - req_id: req.req_id, - resp_type: match crate::exec_req_type::execute_req_type( - &self, - req.req_type, - is_whitelisted, - ) - .await - { - Ok(resp_type) => resp_type, - Err(e) => BcaRespTypeV0::Error(e.0), - }, - }), - _ => BcaResp::UnsupportedVersion, - } - } -} - -#[cfg(not(test))] -impl BcaExecutor { - #[inline(always)] - pub fn dbs_reader(&self) -> DbsReaderImpl { - self.dbs_reader - } -} - -#[cfg(test)] -mod tests { - use super::*; - pub use dubp::{ - block::prelude::*, - crypto::{ - hashs::Hash, - keys::{ed25519::PublicKey, KeyPair, Seed32}, - }, - documents::transaction::TransactionInputV10, - wallet::prelude::*, - }; - pub use duniter_bca_types::BcaReqV0; - pub use duniter_dbs::databases::bc_v2::{BcV2DbReadable, BcV2DbRo}; - pub use duniter_dbs::databases::cm_v1::{CmV1Db, CmV1DbReadable}; - pub use duniter_dbs::databases::txs_mp_v2::{TxsMpV2Db, TxsMpV2DbReadable}; - pub use duniter_dbs::BlockMetaV2; - pub use duniter_global::{CurrentMeta, MockAsyncAccessor}; - pub use duniter_gva_dbs_reader::MockDbsReader; - pub use futures::TryStreamExt; - - pub type AsyncAccessor = duniter_dbs::kv_typed::prelude::Arc<MockAsyncAccessor>; - pub type DbsReaderImpl = duniter_dbs::kv_typed::prelude::Arc<MockDbsReader>; - - impl BcaExecutor { - #[inline(always)] - pub fn dbs_reader(&self) -> DbsReaderImpl { - self.dbs_reader.clone() - } - } - - pub(crate) fn create_bca_executor( - mock_cm: MockAsyncAccessor, - mock_dbs_reader: MockDbsReader, - ) -> KvResult<BcaExecutor> { - let dbs = SharedDbs::mem()?; - let threadpool = - fast_threadpool::ThreadPool::start(fast_threadpool::ThreadPoolConfig::low(), dbs); - Ok(BcaExecutor { - cm_accessor: duniter_dbs::kv_typed::prelude::Arc::new(mock_cm), - currency: "g1".to_owned(), - dbs_pool: threadpool.into_async_handler(), - dbs_reader: duniter_dbs::kv_typed::prelude::Arc::new(mock_dbs_reader), - self_keypair: Ed25519KeyPair::from_seed( - Seed32::random().expect("fail to gen random seed"), - ), - software_version: "test", - txs_mempool: duniter_mempools::TxsMempool::new(10), - }) - } - - pub(crate) fn io_stream<B: AsRef<[u8]>>( - bytes: B, - ) -> impl TryStream<Ok = B, Error = std::io::Error> { - futures::stream::iter(std::iter::once(Ok(bytes))) - } - - #[tokio::test] - async fn test_one_req_ok() -> Result<(), bincode::Error> { - let req = BcaReq::V0(BcaReqV0 { - req_id: 42, - req_type: BcaReqTypeV0::MembersCount, - }); - assert_eq!(bincode_opts().serialized_size(&req)?, 3); - let mut bytes = [0u8; 7]; - - bincode_opts().serialize_into(&mut bytes[4..], &req)?; - bytes[3] = 3; - - use bincode::Options; - //println!("bytes_for_bincode={:?}", &bytes[4..]); - assert_eq!(req, bincode_opts().deserialize(&bytes[4..])?); - - let mut mock_cm = MockAsyncAccessor::new(); - mock_cm - .expect_get_current_meta::<u64>() - .times(1) - .returning(|f| Some(f(&CurrentMeta::default()))); - let bca_executor = create_bca_executor(mock_cm, MockDbsReader::new()) - .expect("fail to create bca executor"); - - //println!("bytes={:?}", bytes); - let bytes_res = bca_executor.execute(io_stream(bytes), false).await; - //println!("bytes_res={:?}", bytes_res); - let bca_res: Vec<Result<BcaResp, BcaReqExecError>> = - AsyncBincodeReader::<_, Result<BcaResp, BcaReqExecError>>::from(&bytes_res[..]) - .try_collect::<Vec<_>>() - .await?; - - assert_eq!( - bca_res, - vec![Ok(BcaResp::V0(BcaRespV0 { - req_id: 42, - resp_type: BcaRespTypeV0::MembersCount(0) - }))] - ); - - Ok(()) - } - - #[tokio::test] - async fn test_one_req_invalid() -> Result<(), bincode::Error> { - let req = BcaReq::V0(BcaReqV0 { - req_id: 42, - req_type: BcaReqTypeV0::MembersCount, - }); - assert_eq!(bincode_opts().serialized_size(&req)?, 3); - let mut bytes = [0u8; 7]; - - bincode_opts().serialize_into(&mut bytes[4..], &req)?; - bytes[3] = 2; - - use bincode::Options; - //println!("bytes_for_bincode={:?}", &bytes[4..]); - assert_eq!(req, bincode_opts().deserialize(&bytes[4..])?); - - let bca_executor = create_bca_executor(MockAsyncAccessor::new(), MockDbsReader::new()) - .expect("fail to create bca executor"); - - //println!("bytes={:?}", bytes); - let bytes_res = bca_executor.execute(io_stream(bytes), false).await; - //println!("bytes_res={:?}", bytes_res); - let bca_res: Vec<Result<BcaResp, BcaReqExecError>> = - AsyncBincodeReader::<_, Result<BcaResp, BcaReqExecError>>::from(&bytes_res[..]) - .try_collect::<Vec<_>>() - .await?; - - assert_eq!( - bca_res, - vec![Err(BcaReqExecError::InvalidReq( - "io error: unexpected end of file".to_owned() - ))] - ); - - Ok(()) - } - - #[tokio::test] - async fn test_two_reqs_ok() -> Result<(), bincode::Error> { - let req1 = BcaReq::V0(BcaReqV0 { - req_id: 42, - req_type: BcaReqTypeV0::Ping, - }); - assert_eq!(bincode_opts().serialized_size(&req1)?, 3); - let req2 = BcaReq::V0(BcaReqV0 { - req_id: 57, - req_type: BcaReqTypeV0::MembersCount, - }); - assert_eq!(bincode_opts().serialized_size(&req2)?, 3); - - let mut bytes = [0u8; 14]; - bincode_opts().serialize_into(&mut bytes[4..], &req1)?; - bytes[3] = 3; - bincode_opts().serialize_into(&mut bytes[11..], &req2)?; - bytes[10] = 3; - - let mut mock_cm = MockAsyncAccessor::new(); - mock_cm - .expect_get_current_meta::<u64>() - .times(1) - .returning(|f| Some(f(&CurrentMeta::default()))); - let bca_executor = create_bca_executor(mock_cm, MockDbsReader::new()) - .expect("fail to create bca executor"); - - //println!("bytes={:?}", bytes); - let bytes_res = bca_executor.execute(io_stream(bytes), false).await; - //println!("bytes_res={:?}", bytes_res); - let bca_res: Vec<Result<BcaResp, BcaReqExecError>> = - AsyncBincodeReader::<_, Result<BcaResp, BcaReqExecError>>::from(&bytes_res[..]) - .try_collect::<Vec<_>>() - .await?; - - assert_eq!( - bca_res, - vec![ - Ok(BcaResp::V0(BcaRespV0 { - req_id: 42, - resp_type: BcaRespTypeV0::Pong - })), - Ok(BcaResp::V0(BcaRespV0 { - req_id: 57, - resp_type: BcaRespTypeV0::MembersCount(0) - })) - ] - ); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/bca/types/Cargo.toml b/rust-libs/modules/gva/bca/types/Cargo.toml deleted file mode 100644 index ef4fc9023..000000000 --- a/rust-libs/modules/gva/bca/types/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "duniter-bca-types" -version = "0.1.0" -authors = ["librelois <elois@duniter.org>"] -license = "AGPL-3.0" -edition = "2018" - -[dependencies] -arrayvec = { version = "0.5.1", features = ["serde"] } -bincode = "1.3" -dubp = { version = "0.51.0" } -serde = { version = "1.0.105", features = ["derive"] } -smallvec = { version = "1.4.0", features = ["serde"] } -thiserror = "1.0.20" - -[features] -default = ["duniter"] - -client = ["dubp/client"] -duniter = ["dubp/duniter"] diff --git a/rust-libs/modules/gva/bca/types/src/amount.rs b/rust-libs/modules/gva/bca/types/src/amount.rs deleted file mode 100644 index 1682a3141..000000000 --- a/rust-libs/modules/gva/bca/types/src/amount.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] -pub enum Amount { - Cents(SourceAmount), - Uds(f64), -} - -impl Default for Amount { - fn default() -> Self { - Self::Cents(SourceAmount::ZERO) - } -} - -impl Amount { - pub fn to_cents(self, ud_amount: SourceAmount) -> SourceAmount { - match self { - Amount::Cents(sa) => sa, - Amount::Uds(f64_) => { - if !f64_.is_finite() || f64_ <= 0f64 { - SourceAmount::ZERO - } else { - SourceAmount::new( - f64::round(ud_amount.amount() as f64 * f64_) as i64, - ud_amount.base(), - ) - } - } - } - } -} diff --git a/rust-libs/modules/gva/bca/types/src/identity.rs b/rust-libs/modules/gva/bca/types/src/identity.rs deleted file mode 100644 index e2302a9bf..000000000 --- a/rust-libs/modules/gva/bca/types/src/identity.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] -pub struct Identity { - pub is_member: bool, - pub username: String, -} diff --git a/rust-libs/modules/gva/bca/types/src/lib.rs b/rust-libs/modules/gva/bca/types/src/lib.rs deleted file mode 100644 index a9b987ba3..000000000 --- a/rust-libs/modules/gva/bca/types/src/lib.rs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -pub mod amount; -pub mod identity; -pub mod prepare_payment; -pub mod rejected_tx; -pub mod utxo; - -use crate::amount::Amount; -use crate::identity::Identity; -use crate::prepare_payment::{PrepareSimplePayment, PrepareSimplePaymentResp}; -use crate::utxo::Utxo; - -use arrayvec::ArrayVec; -use bincode::Options as _; -use dubp::crypto::keys::ed25519::{PublicKey, Signature}; -use dubp::wallet::prelude::*; -use dubp::{common::prelude::Blockstamp, crypto::hashs::Hash}; -use serde::{Deserialize, Serialize}; -use smallvec::SmallVec; -use thiserror::Error; - -// Constants - -pub const MAX_FIRST_UTXOS: usize = 40; - -// Request - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub enum BcaReq { - V0(BcaReqV0), - _V1, -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub struct BcaReqV0 { - pub req_id: usize, - pub req_type: BcaReqTypeV0, -} - -#[allow(clippy::large_enum_variant)] -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub enum BcaReqTypeV0 { - BalancesOfPubkeys(ArrayVec<[PublicKey; 16]>), - FirstUtxosOfPubkeys { - amount_target_opt: Option<Amount>, - pubkeys: ArrayVec<[PublicKey; 16]>, - }, - LastBlockstampOutOfForkWindow, - MembersCount, - PrepareSimplePayment(PrepareSimplePayment), - ProofServerPubkey { - challenge: [u8; 16], - }, - Ping, - SendTxs(Txs), - Identities(ArrayVec<[PublicKey; 16]>), - CurrentUd, - BalancesOfScripts(ArrayVec<[WalletScriptV10; 16]>), -} - -// Request types helpers - -pub type Txs = SmallVec<[dubp::documents::transaction::TransactionDocumentV10; 1]>; - -// Response - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -pub enum BcaResp { - V0(BcaRespV0), - UnsupportedVersion, -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -pub struct BcaRespV0 { - pub req_id: usize, - pub resp_type: BcaRespTypeV0, -} - -#[allow(clippy::large_enum_variant)] -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -pub enum BcaRespTypeV0 { - Error(String), - Balances(ArrayVec<[Option<SourceAmount>; 16]>), - FirstUtxosOfPubkeys(Vec<ArrayVec<[Utxo; MAX_FIRST_UTXOS]>>), - ProofServerPubkey { - challenge: [u8; 16], - server_pubkey: PublicKey, - sig: Signature, - }, - LastBlockstampOutOfForkWindow(Blockstamp), - MembersCount(u64), - PrepareSimplePayment(PrepareSimplePaymentResp), - Pong, - RejectedTxs(Vec<rejected_tx::RejectedTx>), - Identities(ArrayVec<[Option<Identity>; 16]>), - CurrentUd(SourceAmount), -} - -// Result and error - -pub type BcaResult = Result<BcaResp, BcaReqExecError>; - -#[derive(Clone, Debug, Deserialize, Error, PartialEq, Eq, Serialize)] -pub enum BcaReqExecError { - #[error("task cancelled")] - Cancelled, - #[error("Invalid request: {0}")] - InvalidReq(String), - #[error("task panicked")] - Panic, - #[error("Unknown error")] - Unknown, -} - -// Bincode configuration - -pub fn bincode_opts() -> impl bincode::Options { - bincode::options() - .with_limit(u32::max_value() as u64) - .allow_trailing_bytes() -} diff --git a/rust-libs/modules/gva/bca/types/src/prepare_payment.rs b/rust-libs/modules/gva/bca/types/src/prepare_payment.rs deleted file mode 100644 index 2de5d621a..000000000 --- a/rust-libs/modules/gva/bca/types/src/prepare_payment.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use dubp::documents::transaction::TransactionInputV10; - -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] -pub struct PrepareSimplePayment { - pub issuer: PublicKey, - pub amount: Amount, -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -pub struct PrepareSimplePaymentResp { - pub current_block_number: u32, - pub current_block_hash: Hash, - pub current_ud: SourceAmount, - pub inputs: Vec<TransactionInputV10>, - pub inputs_sum: SourceAmount, -} diff --git a/rust-libs/modules/gva/bca/types/src/rejected_tx.rs b/rust-libs/modules/gva/bca/types/src/rejected_tx.rs deleted file mode 100644 index 14b06e52b..000000000 --- a/rust-libs/modules/gva/bca/types/src/rejected_tx.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -pub struct RejectedTx { - pub tx_index: u16, - pub reason: RejectedTxReason, -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -pub enum RejectedTxReason { - DbError(String), - InvalidTx(String), - MempoolFull, - TxAlreadyWritten, -} diff --git a/rust-libs/modules/gva/bca/types/src/utxo.rs b/rust-libs/modules/gva/bca/types/src/utxo.rs deleted file mode 100644 index d7716a808..000000000 --- a/rust-libs/modules/gva/bca/types/src/utxo.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] -pub struct Utxo { - pub amount: SourceAmount, - pub tx_hash: Hash, - pub output_index: u8, -} diff --git a/rust-libs/modules/gva/db/Cargo.toml b/rust-libs/modules/gva/db/Cargo.toml deleted file mode 100644 index a74d1af8f..000000000 --- a/rust-libs/modules/gva/db/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "duniter-gva-db" -version = "0.1.0" -authors = ["elois <elois@duniter.org>"] -description = "Duniter GVA DB" -repository = "https://git.duniter.org/nodes/typescript/duniter" -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -bincode = "1.2.1" -chrono = { version = "0.4.15", optional = true } -duniter-dbs = { path = "../../../duniter-dbs" } -dubp = { version = "0.51.0", features = ["duniter"] } -kv_typed = { path = "../../../tools/kv_typed", default-features = false, features = ["sled_backend"] } -parking_lot = "0.11.0" -paste = "1.0.2" -serde = { version = "1.0.105", features = ["derive"] } -serde_json = "1.0.53" -uninit = "0.4.0" -zerocopy = "0.3.0" - -[dev-dependencies] - -[features] -#default = ["explorer"] - -explorer = ["chrono", "duniter-dbs/explorer", "kv_typed/explorer"] -leveldb_backend = ["kv_typed/leveldb_backend"] diff --git a/rust-libs/modules/gva/db/src/keys.rs b/rust-libs/modules/gva/db/src/keys.rs deleted file mode 100644 index ced890746..000000000 --- a/rust-libs/modules/gva/db/src/keys.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -pub mod gva_utxo_id; -pub mod wallet_hash_with_bn; diff --git a/rust-libs/modules/gva/db/src/keys/gva_utxo_id.rs b/rust-libs/modules/gva/db/src/keys/gva_utxo_id.rs deleted file mode 100644 index 1f624a872..000000000 --- a/rust-libs/modules/gva/db/src/keys/gva_utxo_id.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use uninit::prelude::*; - -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct GvaUtxoIdDbV1([u8; 69]); // script hash ++ block_number ++ tx_hash ++ output_index - -impl Default for GvaUtxoIdDbV1 { - fn default() -> Self { - GvaUtxoIdDbV1([0u8; 69]) - } -} - -impl std::fmt::Display for GvaUtxoIdDbV1 { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}:{}:{}:{}", - self.get_script_hash(), - self.get_block_number(), - self.get_tx_hash(), - self.get_output_index() - ) - } -} - -impl GvaUtxoIdDbV1 { - pub fn get_script_hash(&self) -> Hash { - let mut buffer = uninit_array![u8; 32]; - - buffer.as_out().copy_from_slice(&self.0[..32]); - - Hash(unsafe { std::mem::transmute(buffer) }) - } - pub fn get_block_number(&self) -> u32 { - let mut buffer = uninit_array![u8; 4]; - - buffer.as_out().copy_from_slice(&self.0[32..36]); - - u32::from_be_bytes(unsafe { std::mem::transmute(buffer) }) - } - pub fn get_tx_hash(&self) -> Hash { - let mut buffer = uninit_array![u8; 32]; - - buffer.as_out().copy_from_slice(&self.0[36..68]); - - Hash(unsafe { std::mem::transmute(buffer) }) - } - pub fn get_output_index(&self) -> u8 { - self.0[68] - } - pub fn new( - script: WalletScriptV10, - block_number: u32, - tx_hash: Hash, - output_index: u8, - ) -> Self { - let script_hash = Hash::compute(script.to_string().as_bytes()); - Self::new_(script_hash, block_number, tx_hash, output_index) - } - pub fn new_(script_hash: Hash, block_number: u32, tx_hash: Hash, output_index: u8) -> Self { - // TODO uncomment when feature const_generics became stable ! - /*let mut buffer = uninit_array![u8; 69]; - let (hash_buffer, rest_buffer) = buffer.as_out().split_at_out(32); - let (bn_buffer, rest_buffer) = rest_buffer.split_at_out(4); - let (tx_hash_buffer, output_index_buffer) = rest_buffer.split_at_out(32); - hash_buffer.copy_from_slice(script_hash.as_ref()); - bn_buffer.copy_from_slice(&block_number.to_be_bytes()[..]); - tx_hash_buffer.copy_from_slice(tx_hash.as_ref()); - output_index_buffer.copy_from_slice(&[output_index]); - - Self(unsafe { std::mem::transmute(buffer) })*/ - let mut buffer = [0u8; 69]; - buffer[..32].copy_from_slice(script_hash.as_ref()); - buffer[32..36].copy_from_slice(&block_number.to_be_bytes()[..]); - buffer[36..68].copy_from_slice(tx_hash.as_ref()); - buffer[68] = output_index; - Self(buffer) - } - pub fn script_interval(script_hash: Hash) -> (Self, Self) { - let mut buffer = [0; 69]; - buffer[..32].copy_from_slice(script_hash.as_ref()); - let min = Self(buffer); - let mut buffer = [255; 69]; - buffer[..32].copy_from_slice(script_hash.as_ref()); - let max = Self(buffer); - - (min, max) - } - pub fn script_block_interval( - script_hash: Hash, - block_number_start: u32, - block_number_end: u32, - ) -> (Self, Self) { - ( - Self::new_(script_hash, block_number_start, Hash::default(), 0), - Self::new_(script_hash, block_number_end, Hash::max(), u8::MAX), - ) - } -} - -impl AsBytes for GvaUtxoIdDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(&self.0[..]) - } -} - -impl FromBytes for GvaUtxoIdDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - if bytes.len() == 69 { - // TODO uncomment when feature const_generics became stable ! - /*let mut buffer = uninit_array![u8; 69]; - buffer.as_out().copy_from_slice(bytes); - Ok(Self(unsafe { std::mem::transmute(buffer) }))*/ - let mut buffer = [0u8; 69]; - buffer.copy_from_slice(bytes); - Ok(Self(buffer)) - } else { - Err(CorruptedBytes("db corrupted".to_owned())) - } - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for GvaUtxoIdDbV1 { - fn from_explorer_str(_: &str) -> std::result::Result<Self, FromExplorerKeyErr> { - unimplemented!() - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(self.to_string()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn utxo_gva_id_new() { - let script = WalletScriptV10::single(WalletConditionV10::Csv(86_400)); - let script_hash = Hash::compute(script.to_string().as_bytes()); - let tx_hash = Hash::default(); - let utxo_gva_id = GvaUtxoIdDbV1::new(script, 42, tx_hash, 3); - - assert_eq!(utxo_gva_id.get_script_hash(), script_hash); - assert_eq!(utxo_gva_id.get_block_number(), 42); - assert_eq!(utxo_gva_id.get_tx_hash(), tx_hash); - assert_eq!(utxo_gva_id.get_output_index(), 3); - } -} diff --git a/rust-libs/modules/gva/db/src/keys/wallet_hash_with_bn.rs b/rust-libs/modules/gva/db/src/keys/wallet_hash_with_bn.rs deleted file mode 100644 index bb5c767c1..000000000 --- a/rust-libs/modules/gva/db/src/keys/wallet_hash_with_bn.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -use std::fmt::Display; -use uninit::prelude::*; - -#[derive( - Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, zerocopy::AsBytes, zerocopy::FromBytes, -)] -#[repr(transparent)] -pub struct WalletHashWithBnV1Db([u8; 36]); // wallet_hash ++ block_number - -impl WalletHashWithBnV1Db { - pub fn new(hash: Hash, block_number: BlockNumber) -> Self { - let mut buffer = uninit_array![u8; 36]; - let (hash_buffer, bn_buffer) = buffer.as_out().split_at_out(32); - - hash_buffer.copy_from_slice(hash.as_ref()); - bn_buffer.copy_from_slice(&block_number.0.to_be_bytes()[..]); - - Self(unsafe { std::mem::transmute(buffer) }) - } - pub fn get_wallet_hash(&self) -> Hash { - let mut buffer = uninit_array![u8; 32]; - - buffer.as_out().copy_from_slice(&self.0[..32]); - let bytes: [u8; 32] = unsafe { std::mem::transmute(buffer) }; - - Hash(bytes) - } - pub fn get_block_number(&self) -> u32 { - let mut buffer = uninit_array![u8; 4]; - - buffer.as_out().copy_from_slice(&self.0[32..]); - - u32::from_be_bytes(unsafe { std::mem::transmute(buffer) }) - } - pub fn wallet_hash_interval(wallet_hash: Hash) -> (Self, Self) { - ( - Self::new(wallet_hash, BlockNumber(0)), - Self::new(wallet_hash, BlockNumber(u32::MAX)), - ) - } -} - -impl Default for WalletHashWithBnV1Db { - fn default() -> Self { - WalletHashWithBnV1Db([0u8; 36]) - } -} - -impl Display for WalletHashWithBnV1Db { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}:{}", self.get_wallet_hash(), self.get_block_number()) - } -} - -impl AsBytes for WalletHashWithBnV1Db { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.0.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for WalletHashWithBnV1Db { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - let layout = zerocopy::LayoutVerified::<_, WalletHashWithBnV1Db>::new(bytes) - .ok_or_else(|| CorruptedBytes("corrupted db".to_owned()))?; - Ok(*layout) - } -} - -impl KeyZc for WalletHashWithBnV1Db { - type Ref = Self; -} - -impl ToDumpString for WalletHashWithBnV1Db { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableKey for WalletHashWithBnV1Db { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - let mut source = source.split(':'); - let hash_str = source - .next() - .ok_or_else(|| FromExplorerKeyErr("missing hash".into()))?; - let bn_str = source - .next() - .ok_or_else(|| FromExplorerKeyErr("missing block number".into()))?; - - let hash = Hash::from_hex(hash_str).map_err(|e| FromExplorerKeyErr(e.into()))?; - let block_number = bn_str - .parse() - .map_err(|e: std::num::ParseIntError| FromExplorerKeyErr(e.into()))?; - - Ok(WalletHashWithBnV1Db::new(hash, block_number)) - } - fn to_explorer_string(&self) -> KvResult<String> { - Ok(self.to_string()) - } -} diff --git a/rust-libs/modules/gva/db/src/lib.rs b/rust-libs/modules/gva/db/src/lib.rs deleted file mode 100644 index d19cb94e9..000000000 --- a/rust-libs/modules/gva/db/src/lib.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -mod keys; -mod values; - -pub use keys::gva_utxo_id::GvaUtxoIdDbV1; -pub use keys::wallet_hash_with_bn::WalletHashWithBnV1Db; -pub use values::gva_idty_db::GvaIdtyDbV1; -pub use values::gva_tx::GvaTxDbV1; -pub use values::wallet_script_array::WalletScriptArrayV2; - -pub(crate) use dubp::common::prelude::*; -pub(crate) use dubp::crypto::hashs::Hash; -pub(crate) use dubp::wallet::prelude::*; -pub(crate) use duniter_dbs::smallvec::SmallVec; -pub(crate) use duniter_dbs::{ - CorruptedBytes, HashKeyV2, PubKeyKeyV2, SourceAmountValV2, ToDumpString, WalletConditionsV2, -}; -pub(crate) use kv_typed::db_schema; -pub(crate) use kv_typed::prelude::*; -pub(crate) use serde::{Deserialize, Serialize}; -pub(crate) use std::collections::BTreeSet; - -db_schema!( - GvaV1, - [ - ["blocks_by_common_time", BlocksByCommonTime, U64BE, u32], - ["blocks_with_ud", BlocksWithUd, U32BE, ()], - ["blockchain_time", BlockchainTime, U32BE, u64], - ["txs", Txs, HashKeyV2, GvaTxDbV1], - ["txs_by_block", TxsByBlock, U32BE, Vec<Hash>], - ["txs_by_issuer", TxsByIssuer, WalletHashWithBnV1Db, BTreeSet<Hash>], - ["txs_by_recipient", TxsByRecipient, WalletHashWithBnV1Db, BTreeSet<Hash>], - [ - "scripts_by_pubkey", - ScriptsByPubkey, - PubKeyKeyV2, - WalletScriptArrayV2 - ], - [ - "gva_utxos", - GvaUtxos, - GvaUtxoIdDbV1, - SourceAmountValV2 - ], - ["balances", Balances, WalletConditionsV2, SourceAmountValV2], - ["gva_identities", GvaIdentities, PubKeyKeyV2, GvaIdtyDbV1], - ] -); diff --git a/rust-libs/modules/gva/db/src/values.rs b/rust-libs/modules/gva/db/src/values.rs deleted file mode 100644 index ed42095fa..000000000 --- a/rust-libs/modules/gva/db/src/values.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -pub mod gva_idty_db; -pub mod gva_tx; -pub mod wallet_script_array; diff --git a/rust-libs/modules/gva/db/src/values/gva_idty_db.rs b/rust-libs/modules/gva/db/src/values/gva_idty_db.rs deleted file mode 100644 index 9bb918af8..000000000 --- a/rust-libs/modules/gva/db/src/values/gva_idty_db.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] -pub struct GvaIdtyDbV1 { - pub is_member: bool, - pub joins: SmallVec<[BlockNumber; 2]>, - pub leaves: BTreeSet<BlockNumber>, - pub first_ud: Option<BlockNumber>, -} - -impl AsBytes for GvaIdtyDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(&bincode::serialize(&self).unwrap_or_else(|_| unreachable!())) - } -} - -impl kv_typed::prelude::FromBytes for GvaIdtyDbV1 { - type Err = bincode::Error; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(bytes) - } -} - -impl ToDumpString for GvaIdtyDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for GvaIdtyDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - serde_json::from_str(source).map_err(|e| FromExplorerValueErr(e.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(&self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/modules/gva/db/src/values/gva_tx.rs b/rust-libs/modules/gva/db/src/values/gva_tx.rs deleted file mode 100644 index 258fae77c..000000000 --- a/rust-libs/modules/gva/db/src/values/gva_tx.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -use dubp::documents::transaction::TransactionDocumentV10; - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] -pub struct GvaTxDbV1 { - pub tx: TransactionDocumentV10, - pub written_block: Blockstamp, - pub written_time: i64, -} - -impl AsBytes for GvaTxDbV1 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - let bytes = bincode::serialize(self).unwrap_or_else(|_| unreachable!()); - f(bytes.as_ref()) - } -} - -impl kv_typed::prelude::FromBytes for GvaTxDbV1 { - type Err = CorruptedBytes; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - bincode::deserialize(&bytes).map_err(|e| CorruptedBytes(format!("{}: '{:?}'", e, bytes))) - } -} - -impl ToDumpString for GvaTxDbV1 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for GvaTxDbV1 { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Self::from_bytes(source.as_bytes()).map_err(|e| FromExplorerValueErr(e.0.into())) - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - serde_json::to_value(self).map_err(|e| KvError::DeserError(e.into())) - } -} diff --git a/rust-libs/modules/gva/db/src/values/wallet_script_array.rs b/rust-libs/modules/gva/db/src/values/wallet_script_array.rs deleted file mode 100644 index d0b4fa932..000000000 --- a/rust-libs/modules/gva/db/src/values/wallet_script_array.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -#[derive(Debug, Default, PartialEq)] -pub struct WalletScriptArrayV2(pub std::collections::HashSet<WalletScriptV10>); - -impl AsBytes for WalletScriptArrayV2 { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(&bincode::serialize(&self.0).unwrap_or_else(|_| unreachable!())) - } -} - -impl kv_typed::prelude::FromBytes for WalletScriptArrayV2 { - type Err = bincode::Error; - - fn from_bytes(bytes: &[u8]) -> std::result::Result<Self, Self::Err> { - Ok(Self(bincode::deserialize(bytes)?)) - } -} - -impl ToDumpString for WalletScriptArrayV2 { - fn to_dump_string(&self) -> String { - todo!() - } -} - -#[cfg(feature = "explorer")] -impl ExplorableValue for WalletScriptArrayV2 { - fn from_explorer_str(_: &str) -> std::result::Result<Self, FromExplorerValueErr> { - unimplemented!() - } - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::Array( - self.0 - .iter() - .map(|script| serde_json::Value::String(script.to_string())) - .collect(), - )) - } -} diff --git a/rust-libs/modules/gva/dbs-reader/Cargo.toml b/rust-libs/modules/gva/dbs-reader/Cargo.toml deleted file mode 100644 index 5236284f2..000000000 --- a/rust-libs/modules/gva/dbs-reader/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "duniter-gva-dbs-reader" -version = "0.1.0" -authors = ["elois <elois@duniter.org>"] -description = "Duniter GVA DBs read operations" -repository = "https://git.duniter.org/nodes/typescript/duniter" -keywords = ["dubp", "duniter", "blockchain", "database"] -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[features] -mock = ["mockall"] - -[dependencies] -anyhow = "1.0.34" -arrayvec = "0.5.1" -duniter-bca-types = { path = "../bca/types" } -duniter-dbs = { path = "../../../duniter-dbs" } -duniter-gva-db = { path = "../db" } -dubp = { version = "0.51.0", features = ["duniter"] } -mockall = { version = "0.9.1", optional = true } -resiter = "0.4.0" - -[dev-dependencies] -duniter-dbs = { path = "../../../duniter-dbs", features = ["mem"] } -maplit = "1.0.2" -smallvec = { version = "1.4.0", features = ["serde", "write"] } -unwrap = "1.2.1" diff --git a/rust-libs/modules/gva/dbs-reader/src/block.rs b/rust-libs/modules/gva/dbs-reader/src/block.rs deleted file mode 100644 index c4704b4c9..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/block.rs +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (C) 2021 Pascal Engélibert -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] -pub struct BlockCursor { - pub number: BlockNumber, -} -impl std::fmt::Display for BlockCursor { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.number) - } -} - -impl FromStr for BlockCursor { - type Err = WrongCursor; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - Ok(Self { - number: s.parse().map_err(|_| WrongCursor)?, - }) - } -} - -impl DbsReaderImpl { - pub(super) fn block_( - &self, - bc_db: &BcV2DbRo<FileBackend>, - number: U32BE, - ) -> KvResult<Option<duniter_dbs::BlockMetaV2>> { - bc_db.blocks_meta().get(&number) - } - - pub(super) fn blocks_( - &self, - bc_db: &BcV2DbRo<FileBackend>, - page_info: PageInfo<BlockCursor>, - ) -> KvResult<PagedData<Vec<(BlockCursor, duniter_dbs::BlockMetaV2)>>> { - let last_block_number = bc_db - .blocks_meta() - .iter_rev(.., |it| it.values().next_res())? - .ok_or_else(|| KvError::Custom("Empty blockchain".into()))? - .number; - - let first_cursor_opt = if page_info.not_all() { - Some(BlockCursor { - number: BlockNumber(0), - }) - } else { - None - }; - - let last_cursor_opt = if page_info.not_all() { - Some(BlockCursor { - number: BlockNumber(last_block_number), - }) - } else { - None - }; - - let k_min = U32BE(if page_info.order { - page_info.pos.map_or_else(|| 0, |pos| pos.number.0) - } else { - page_info.limit_opt.map_or_else( - || 0, - |limit| { - page_info - .pos - .map_or_else(|| last_block_number + 1, |pos| pos.number.0) - .saturating_sub(limit.get() as u32 - 1) - }, - ) - }); - let k_max = U32BE(if page_info.order { - page_info.limit_opt.map_or_else( - || last_block_number + 1, - |limit| { - page_info.pos.map_or_else( - || limit.get() as u32, - |pos| pos.number.0.saturating_add(limit.get() as u32), - ) - }, - ) - } else { - page_info.pos.map_or_else( - || last_block_number + 1, - |pos| pos.number.0.saturating_add(1), - ) - }); - - let blocks: Vec<(BlockCursor, duniter_dbs::BlockMetaV2)> = if page_info.order { - bc_db.blocks_meta().iter(k_min..k_max, blocks_inner)? - } else { - bc_db.blocks_meta().iter_rev(k_min..k_max, blocks_inner)? - }; - - Ok(PagedData { - has_next_page: has_next_page( - blocks - .iter() - .map(|(block_cursor, _block)| block_cursor.into()), - last_cursor_opt, - page_info, - page_info.order, - ), - has_previous_page: has_previous_page( - blocks - .iter() - .map(|(block_cursor, _block)| block_cursor.into()), - first_cursor_opt, - page_info, - page_info.order, - ), - data: blocks, - }) - } -} - -fn blocks_inner<I>(blocks_iter: I) -> KvResult<Vec<(BlockCursor, duniter_dbs::BlockMetaV2)>> -where - I: Iterator<Item = KvResult<(U32BE, BlockMetaV2)>>, -{ - blocks_iter - .map(|block_res| { - block_res.map(|block| { - ( - BlockCursor { - number: BlockNumber(block.0 .0), - }, - block.1, - ) - }) - }) - .collect() -} - -#[cfg(test)] -mod tests { - use super::*; - use duniter_dbs::databases::bc_v2::BcV2DbWritable; - use std::num::NonZeroUsize; - - #[test] - fn test_block() -> KvResult<()> { - let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?; - let bc_db_ro = bc_db.get_ro_handler(); - let db_reader = DbsReaderImpl::mem(); - - bc_db - .blocks_meta_write() - .upsert(U32BE(0), duniter_dbs::BlockMetaV2::default())?; - - assert_eq!( - db_reader.block(&bc_db_ro, U32BE(0))?, - Some(duniter_dbs::BlockMetaV2::default()) - ); - - Ok(()) - } - - #[test] - fn test_blocks() -> KvResult<()> { - let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?; - let bc_db_ro = bc_db.get_ro_handler(); - let db_reader = DbsReaderImpl::mem(); - - for i in 0..20 { - bc_db.blocks_meta_write().upsert( - U32BE(i), - duniter_dbs::BlockMetaV2 { - number: i, - ..Default::default() - }, - )?; - } - - let blocks = db_reader.blocks( - &bc_db_ro, - PageInfo { - pos: Some(BlockCursor { - number: BlockNumber(10), - }), - order: true, - limit_opt: NonZeroUsize::new(3), - }, - )?; - - assert_eq!(blocks.data.len(), 3); - assert_eq!(blocks.data[0].1.number, 10); - assert_eq!(blocks.data[1].1.number, 11); - assert_eq!(blocks.data[2].1.number, 12); - assert!(blocks.has_previous_page); - assert!(blocks.has_next_page); - - let blocks = db_reader.blocks( - &bc_db_ro, - PageInfo { - pos: Some(BlockCursor { - number: BlockNumber(10), - }), - order: false, - limit_opt: NonZeroUsize::new(3), - }, - )?; - - assert_eq!(blocks.data.len(), 3); - assert_eq!(blocks.data[0].1.number, 10); - assert_eq!(blocks.data[1].1.number, 9); - assert_eq!(blocks.data[2].1.number, 8); - assert!(blocks.has_previous_page); - assert!(blocks.has_next_page); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/dbs-reader/src/current_frame.rs b/rust-libs/modules/gva/dbs-reader/src/current_frame.rs deleted file mode 100644 index 4ca4c48dc..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/current_frame.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use duniter_dbs::BlockMetaV2; - -use crate::*; - -impl DbsReaderImpl { - pub(super) fn get_current_frame_<BcDb: 'static + BcV2DbReadable>( - &self, - bc_db: &BcDb, - current_block_meta: &BlockMetaV2, - ) -> anyhow::Result<Vec<BlockMetaV2>> { - let issuers_frame = current_block_meta.issuers_frame; - let start = U32BE(current_block_meta.number + 1 - issuers_frame as u32); - bc_db - .blocks_meta() - .iter_rev(start.., |it| it.values().collect::<KvResult<_>>()) - .map_err(Into::into) - } -} diff --git a/rust-libs/modules/gva/dbs-reader/src/find_inputs.rs b/rust-libs/modules/gva/dbs-reader/src/find_inputs.rs deleted file mode 100644 index a896ed579..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/find_inputs.rs +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::{ - uds_of_pubkey::UdsWithSum, - utxos::{UtxoCursor, UtxosWithSum}, - *, -}; -use dubp::{documents::transaction::TransactionInputV10, wallet::prelude::*}; - -pub(super) const MIN_AMOUNT: i64 = 100; - -impl DbsReaderImpl { - pub(super) fn find_inputs_<TxsMpDb: 'static + TxsMpV2DbReadable>( - &self, - bc_db: &BcV2DbRo<FileBackend>, - txs_mp_db: &TxsMpDb, - amount: SourceAmount, - script: &WalletScriptV10, - use_mempool_sources: bool, - ) -> anyhow::Result<(Vec<TransactionInputV10>, SourceAmount)> { - // Pending UTXOs - let (mut inputs, mut inputs_sum) = if use_mempool_sources { - txs_mp_db - .outputs_by_script() - .get_ref_slice(duniter_dbs::WalletConditionsV2::from_ref(script), |utxos| { - let mut sum = SourceAmount::ZERO; - let inputs = utxos - .iter() - .filter(|utxo| { - !txs_mp_db - .utxos_ids() - .contains_key(&UtxoIdDbV2(*utxo.tx_hash(), utxo.output_index())) - .unwrap_or(true) - }) - .copied() - .map(|utxo| { - let amount = *utxo.amount(); - sum = sum + amount; - TransactionInputV10 { - amount, - id: SourceIdV10::Utxo(UtxoIdV10 { - tx_hash: *utxo.tx_hash(), - output_index: utxo.output_index() as usize, - }), - } - }) - .collect(); - - Ok((inputs, sum)) - })? - .unwrap_or((Vec::with_capacity(500), SourceAmount::ZERO)) - } else { - (Vec::with_capacity(500), SourceAmount::ZERO) - }; - // UDs - if script.nodes.is_empty() { - if let WalletSubScriptV10::Single(WalletConditionV10::Sig(issuer)) = script.root { - let pending_uds_bn = txs_mp_db.uds_ids().iter(.., |it| { - it.keys() - .map_ok(|duniter_dbs::UdIdV2(_pk, bn)| bn) - .collect::<KvResult<_>>() - })?; - - let PagedData { - data: UdsWithSum { uds, sum: uds_sum }, - .. - } = self.unspent_uds_of_pubkey( - bc_db, - issuer, - PageInfo::default(), - Some(pending_uds_bn), - Some(amount - inputs_sum), - )?; - inputs.extend(uds.into_iter().map(|(block_number, source_amount)| { - TransactionInputV10 { - amount: source_amount, - id: SourceIdV10::Ud(UdSourceIdV10 { - issuer, - block_number, - }), - } - })); - inputs_sum = inputs_sum + uds_sum; - } - } - if inputs_sum < amount { - // Written UTXOs - let PagedData { - data: - UtxosWithSum { - utxos: written_utxos, - sum: written_utxos_sum, - }, - .. - } = self.find_script_utxos( - txs_mp_db, - Some(amount - inputs_sum), - PageInfo::default(), - &script, - )?; - inputs.extend(written_utxos.into_iter().map( - |( - UtxoCursor { - tx_hash, - output_index, - .. - }, - source_amount, - )| TransactionInputV10 { - amount: source_amount, - id: SourceIdV10::Utxo(UtxoIdV10 { - tx_hash, - output_index: output_index as usize, - }), - }, - )); - - Ok((inputs, inputs_sum + written_utxos_sum)) - } else { - Ok((inputs, inputs_sum)) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use duniter_dbs::{ - databases::{bc_v2::BcV2DbWritable, txs_mp_v2::TxsMpV2DbWritable}, - BlockMetaV2, SourceAmountValV2, UdIdV2, UtxoIdDbV2, UtxoValV2, WalletConditionsV2, - }; - use duniter_gva_db::{GvaUtxoIdDbV1, GvaV1DbWritable}; - - const UD0: i64 = 100; - - #[test] - fn test_find_inputs() -> anyhow::Result<()> { - let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?; - let bc_db_ro = bc_db.get_ro_handler(); - let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?; - let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) }); - let txs_mp_db = - duniter_dbs::databases::txs_mp_v2::TxsMpV2Db::<Mem>::open(MemConf::default())?; - - let b0 = BlockMetaV2 { - dividend: Some(SourceAmount::with_base0(UD0)), - ..Default::default() - }; - let pk = PublicKey::default(); - let script = WalletScriptV10::single(WalletConditionV10::Sig(pk)); - let mut pending_utxos = BTreeSet::new(); - pending_utxos.insert(UtxoValV2::new( - SourceAmount::with_base0(900), - Hash::default(), - 10, - )); - - bc_db.blocks_meta_write().upsert(U32BE(0), b0)?; - bc_db - .uds_reval_write() - .upsert(U32BE(0), SourceAmountValV2(SourceAmount::with_base0(UD0)))?; - bc_db - .uds_write() - .upsert(UdIdV2(PublicKey::default(), BlockNumber(0)), ())?; - gva_db - .blockchain_time_write() - .upsert(U32BE(0), b0.median_time)?; - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script.clone(), 0, Hash::default(), 0), - SourceAmountValV2(SourceAmount::with_base0(500)), - )?; - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script.clone(), 0, Hash::default(), 1), - SourceAmountValV2(SourceAmount::with_base0(800)), - )?; - txs_mp_db - .outputs_by_script_write() - .upsert(WalletConditionsV2(script.clone()), pending_utxos)?; - - // Gen tx1 - let (inputs, inputs_sum) = db_reader.find_inputs( - &bc_db_ro, - &txs_mp_db, - SourceAmount::with_base0(550), - &script, - false, - )?; - assert_eq!(inputs.len(), 2); - assert_eq!(inputs_sum, SourceAmount::with_base0(600)); - - // Insert tx1 inputs in mempool - txs_mp_db - .uds_ids_write() - .upsert(UdIdV2(pk, BlockNumber(0)), ())?; - txs_mp_db - .utxos_ids_write() - .upsert(UtxoIdDbV2(Hash::default(), 0), ())?; - - // Gen tx2 - let (inputs, inputs_sum) = db_reader.find_inputs( - &bc_db_ro, - &txs_mp_db, - SourceAmount::with_base0(550), - &script, - false, - )?; - assert_eq!(inputs.len(), 1); - assert_eq!(inputs_sum, SourceAmount::with_base0(800)); - - // Insert tx2 inputs in mempool - txs_mp_db - .utxos_ids_write() - .upsert(UtxoIdDbV2(Hash::default(), 1), ())?; - - // Gen tx3 (use pending utxo) - let (inputs, inputs_sum) = db_reader.find_inputs( - &bc_db_ro, - &txs_mp_db, - SourceAmount::with_base0(750), - &script, - true, - )?; - assert_eq!(inputs.len(), 1); - assert_eq!(inputs_sum, SourceAmount::with_base0(900)); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/dbs-reader/src/idty.rs b/rust-libs/modules/gva/dbs-reader/src/idty.rs deleted file mode 100644 index 4925f9a59..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/idty.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -impl DbsReaderImpl { - pub(super) fn idty_( - &self, - bc_db: &BcV2DbRo<FileBackend>, - pubkey: PublicKey, - ) -> KvResult<Option<duniter_dbs::IdtyDbV2>> { - bc_db.identities().get( - &duniter_dbs::PubKeyKeyV2::from_bytes(pubkey.as_ref()) - .map_err(|e| KvError::DeserError(Box::new(e)))?, - ) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use duniter_dbs::databases::bc_v2::BcV2DbWritable; - - #[test] - fn test_idty() -> KvResult<()> { - let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?; - let bc_db_ro = bc_db.get_ro_handler(); - let db_reader = DbsReaderImpl::mem(); - let pk = PublicKey::default(); - - bc_db - .identities_write() - .upsert(PubKeyKeyV2(pk), duniter_dbs::IdtyDbV2::default())?; - - assert_eq!( - db_reader.idty(&bc_db_ro, pk)?, - Some(duniter_dbs::IdtyDbV2::default()) - ); - - bc_db.identities_write().upsert( - PubKeyKeyV2(pk), - duniter_dbs::IdtyDbV2 { - is_member: true, - username: String::from("JohnDoe"), - }, - )?; - - assert_eq!( - db_reader.idty(&bc_db_ro, pk)?, - Some(duniter_dbs::IdtyDbV2 { - is_member: true, - username: String::from("JohnDoe"), - }) - ); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/dbs-reader/src/lib.rs b/rust-libs/modules/gva/dbs-reader/src/lib.rs deleted file mode 100644 index 8e9cdb33a..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/lib.rs +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -pub mod block; -pub mod current_frame; -pub mod find_inputs; -pub mod idty; -pub mod network; -pub mod pagination; -pub mod txs_history; -pub mod uds_of_pubkey; -pub mod utxos; - -pub use crate::pagination::{PageInfo, PagedData}; -pub use duniter_bca_types::MAX_FIRST_UTXOS; - -use crate::pagination::{has_next_page, has_previous_page}; -use arrayvec::ArrayVec; -use dubp::common::crypto::keys::ed25519::PublicKey; -use dubp::documents::transaction::TransactionDocumentV10; -use dubp::{block::DubpBlockV10, common::crypto::hashs::Hash}; -use dubp::{common::prelude::BlockNumber, wallet::prelude::*}; -use duniter_bca_types::utxo::Utxo; -use duniter_dbs::{databases::network_v1::NetworkV1DbReadable, FileBackend}; -use duniter_dbs::{ - databases::{ - bc_v2::{BcV2DbReadable, BcV2DbRo}, - cm_v1::CmV1DbReadable, - txs_mp_v2::TxsMpV2DbReadable, - }, - BlockMetaV2, -}; -use duniter_dbs::{kv_typed::prelude::*, HashKeyV2, PubKeyKeyV2, SourceAmountValV2, UtxoIdDbV2}; -use duniter_gva_db::{GvaIdtyDbV1, GvaTxDbV1, GvaUtxoIdDbV1, GvaV1DbReadable, GvaV1DbRo}; -use resiter::filter::Filter; -use resiter::filter_map::FilterMap; -use resiter::flatten::Flatten; -use resiter::map::Map; -use std::{ - collections::{BTreeSet, VecDeque}, - num::NonZeroUsize, - str::FromStr, -}; - -#[derive(Clone, Copy, Debug)] -pub struct WrongCursor; -impl std::fmt::Display for WrongCursor { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "wrong cursor") - } -} -impl std::error::Error for WrongCursor {} - -#[cfg_attr(feature = "mock", mockall::automock)] -pub trait DbsReader { - fn all_uds_of_pubkey( - &self, - bc_db: &BcV2DbRo<FileBackend>, - pubkey: PublicKey, - page_info: PageInfo<BlockNumber>, - ) -> KvResult<PagedData<uds_of_pubkey::UdsWithSum>>; - fn block(&self, bc_db: &BcV2DbRo<FileBackend>, number: U32BE) -> KvResult<Option<BlockMetaV2>>; - fn blocks( - &self, - bc_db: &BcV2DbRo<FileBackend>, - page_info: PageInfo<block::BlockCursor>, - ) -> KvResult<PagedData<Vec<(block::BlockCursor, BlockMetaV2)>>>; - fn endpoints<Db: 'static + NetworkV1DbReadable>( - &self, - network_db: &Db, - api_list: Vec<String>, - ) -> KvResult<Vec<String>>; - fn find_inputs<TxsMpDb: 'static + TxsMpV2DbReadable>( - &self, - bc_db: &BcV2DbRo<FileBackend>, - txs_mp_db: &TxsMpDb, - amount: SourceAmount, - script: &WalletScriptV10, - use_mempool_sources: bool, - ) -> anyhow::Result<( - Vec<dubp::documents::transaction::TransactionInputV10>, - SourceAmount, - )>; - fn find_script_utxos<TxsMpDb: 'static + TxsMpV2DbReadable>( - &self, - txs_mp_db_ro: &TxsMpDb, - amount_target_opt: Option<SourceAmount>, - page_info: PageInfo<utxos::UtxoCursor>, - script: &WalletScriptV10, - ) -> anyhow::Result<PagedData<utxos::UtxosWithSum>>; - fn first_scripts_utxos( - &self, - amount_target_opt: Option<SourceAmount>, - first: usize, - scripts: &[WalletScriptV10], - ) -> anyhow::Result<Vec<arrayvec::ArrayVec<[Utxo; MAX_FIRST_UTXOS]>>>; - fn get_account_balance( - &self, - account_script: &WalletScriptV10, - ) -> KvResult<Option<SourceAmountValV2>>; - fn get_blockchain_time(&self, block_number: BlockNumber) -> anyhow::Result<u64>; - fn get_current_block<CmDb: 'static + CmV1DbReadable>( - &self, - cm_db: &CmDb, - ) -> KvResult<Option<DubpBlockV10>>; - fn get_current_frame<BcDb: 'static + BcV2DbReadable>( - &self, - bc_db: &BcDb, - current_block_meta: &BlockMetaV2, - ) -> anyhow::Result<Vec<BlockMetaV2>>; - fn get_txs_history_bc_received( - &self, - from: Option<u64>, - page_info: PageInfo<txs_history::TxBcCursor>, - script_hash: Hash, - to: Option<u64>, - ) -> KvResult<PagedData<VecDeque<duniter_gva_db::GvaTxDbV1>>>; - fn get_txs_history_bc_sent( - &self, - from: Option<u64>, - page_info: PageInfo<txs_history::TxBcCursor>, - script_hash: Hash, - to: Option<u64>, - ) -> KvResult<PagedData<VecDeque<duniter_gva_db::GvaTxDbV1>>>; - fn get_txs_history_mempool<TxsMpDb: 'static + TxsMpV2DbReadable>( - &self, - txs_mp_db_ro: &TxsMpDb, - pubkey: PublicKey, - ) -> KvResult<(Vec<TransactionDocumentV10>, Vec<TransactionDocumentV10>)>; - fn idty( - &self, - bc_db: &BcV2DbRo<FileBackend>, - pubkey: PublicKey, - ) -> KvResult<Option<duniter_dbs::IdtyDbV2>>; - fn peers_and_heads<DB: 'static + NetworkV1DbReadable>( - &self, - dunp_db: &DB, - ) -> KvResult<Vec<(duniter_dbs::PeerCardDbV1, Vec<duniter_dbs::DunpHeadDbV1>)>>; - fn unspent_uds_of_pubkey( - &self, - bc_db: &BcV2DbRo<FileBackend>, - pubkey: PublicKey, - page_info: PageInfo<BlockNumber>, - bn_to_exclude_opt: Option<std::collections::BTreeSet<BlockNumber>>, - amount_target_opt: Option<SourceAmount>, - ) -> KvResult<PagedData<uds_of_pubkey::UdsWithSum>>; -} - -#[derive(Clone, Copy, Debug)] -pub struct DbsReaderImpl(&'static GvaV1DbRo<FileBackend>); - -pub fn create_dbs_reader(gva_db_ro: &'static GvaV1DbRo<FileBackend>) -> DbsReaderImpl { - DbsReaderImpl(gva_db_ro) -} - -impl DbsReader for DbsReaderImpl { - fn all_uds_of_pubkey( - &self, - bc_db: &BcV2DbRo<FileBackend>, - pubkey: PublicKey, - page_info: PageInfo<BlockNumber>, - ) -> KvResult<PagedData<uds_of_pubkey::UdsWithSum>> { - self.all_uds_of_pubkey_(bc_db, pubkey, page_info) - } - - fn block(&self, bc_db: &BcV2DbRo<FileBackend>, number: U32BE) -> KvResult<Option<BlockMetaV2>> { - self.block_(bc_db, number) - } - - fn blocks( - &self, - bc_db: &BcV2DbRo<FileBackend>, - page_info: PageInfo<block::BlockCursor>, - ) -> KvResult<PagedData<Vec<(block::BlockCursor, BlockMetaV2)>>> { - self.blocks_(bc_db, page_info) - } - - fn endpoints<Db: 'static + NetworkV1DbReadable>( - &self, - network_db: &Db, - api_list: Vec<String>, - ) -> KvResult<Vec<String>> { - self.endpoints_(network_db, api_list) - } - - fn find_inputs<TxsMpDb: 'static + TxsMpV2DbReadable>( - &self, - bc_db: &BcV2DbRo<FileBackend>, - txs_mp_db: &TxsMpDb, - amount: SourceAmount, - script: &WalletScriptV10, - use_mempool_sources: bool, - ) -> anyhow::Result<( - Vec<dubp::documents::transaction::TransactionInputV10>, - SourceAmount, - )> { - self.find_inputs_(bc_db, txs_mp_db, amount, script, use_mempool_sources) - } - - fn find_script_utxos<TxsMpDb: 'static + TxsMpV2DbReadable>( - &self, - txs_mp_db_ro: &TxsMpDb, - amount_target_opt: Option<SourceAmount>, - page_info: PageInfo<utxos::UtxoCursor>, - script: &WalletScriptV10, - ) -> anyhow::Result<PagedData<utxos::UtxosWithSum>> { - self.find_script_utxos_(txs_mp_db_ro, amount_target_opt, page_info, script) - } - - fn first_scripts_utxos( - &self, - amount_target_opt: Option<SourceAmount>, - first: usize, - scripts: &[WalletScriptV10], - ) -> anyhow::Result<Vec<ArrayVec<[Utxo; MAX_FIRST_UTXOS]>>> { - self.first_scripts_utxos_(amount_target_opt, first, scripts) - } - - fn get_account_balance( - &self, - account_script: &WalletScriptV10, - ) -> KvResult<Option<SourceAmountValV2>> { - self.0 - .balances() - .get(duniter_dbs::WalletConditionsV2::from_ref(account_script)) - } - - fn get_blockchain_time(&self, block_number: BlockNumber) -> anyhow::Result<u64> { - Ok(self - .0 - .blockchain_time() - .get(&U32BE(block_number.0))? - .unwrap_or_else(|| unreachable!())) - } - - fn get_current_block<CmDb: CmV1DbReadable>( - &self, - cm_db: &CmDb, - ) -> KvResult<Option<DubpBlockV10>> { - Ok(cm_db.current_block().get(&())?.map(|db_block| db_block.0)) - } - - fn get_current_frame<BcDb: 'static + BcV2DbReadable>( - &self, - bc_db: &BcDb, - current_block_meta: &BlockMetaV2, - ) -> anyhow::Result<Vec<BlockMetaV2>> { - self.get_current_frame_(bc_db, current_block_meta) - } - - fn get_txs_history_bc_received( - &self, - from: Option<u64>, - page_info: PageInfo<txs_history::TxBcCursor>, - script_hash: Hash, - to: Option<u64>, - ) -> KvResult<PagedData<VecDeque<GvaTxDbV1>>> { - self.get_txs_history_bc_received_(from, page_info, script_hash, to) - } - - fn get_txs_history_bc_sent( - &self, - from: Option<u64>, - page_info: PageInfo<txs_history::TxBcCursor>, - script_hash: Hash, - to: Option<u64>, - ) -> KvResult<PagedData<VecDeque<GvaTxDbV1>>> { - self.get_txs_history_bc_sent_(from, page_info, script_hash, to) - } - - fn get_txs_history_mempool<TxsMpDb: 'static + TxsMpV2DbReadable>( - &self, - txs_mp_db_ro: &TxsMpDb, - pubkey: PublicKey, - ) -> KvResult<(Vec<TransactionDocumentV10>, Vec<TransactionDocumentV10>)> { - self.get_txs_history_mempool_(txs_mp_db_ro, pubkey) - } - - fn idty( - &self, - bc_db: &BcV2DbRo<FileBackend>, - pubkey: PublicKey, - ) -> KvResult<Option<duniter_dbs::IdtyDbV2>> { - self.idty_(bc_db, pubkey) - } - - fn peers_and_heads<DB: 'static + NetworkV1DbReadable>( - &self, - dunp_db: &DB, - ) -> KvResult<Vec<(duniter_dbs::PeerCardDbV1, Vec<duniter_dbs::DunpHeadDbV1>)>> { - self.peers_and_heads_(dunp_db) - } - - fn unspent_uds_of_pubkey( - &self, - bc_db: &BcV2DbRo<FileBackend>, - pubkey: PublicKey, - page_info: PageInfo<BlockNumber>, - bn_to_exclude_opt: Option<BTreeSet<BlockNumber>>, - amount_target_opt: Option<SourceAmount>, - ) -> KvResult<PagedData<uds_of_pubkey::UdsWithSum>> { - self.unspent_uds_of_pubkey_( - bc_db, - pubkey, - page_info, - bn_to_exclude_opt.as_ref(), - amount_target_opt, - ) - } -} - -#[cfg(test)] -impl DbsReaderImpl { - pub(crate) fn mem() -> Self { - use duniter_gva_db::GvaV1DbWritable; - let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default()) - .expect("fail to create memory gva db"); - create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) }) - } -} diff --git a/rust-libs/modules/gva/dbs-reader/src/network.rs b/rust-libs/modules/gva/dbs-reader/src/network.rs deleted file mode 100644 index 2ec530aa6..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/network.rs +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use dubp::crypto::keys::PublicKey as _; -use duniter_dbs::{databases::network_v1::NetworkV1DbReadable, DunpHeadDbV1, PeerCardDbV1}; - -#[allow(clippy::unnecessary_wraps)] -impl DbsReaderImpl { - pub(super) fn endpoints_<DB: NetworkV1DbReadable>( - &self, - network_db: &DB, - mut api_list: Vec<String>, - ) -> KvResult<Vec<String>> { - if api_list.is_empty() { - return Ok(vec![]); - } - for api in &mut api_list { - api.push(' '); - } - network_db.peers_old().iter(.., |it| { - it.values() - .map_ok(|peer| { - peer.endpoints.into_iter().filter(|endpoint| { - api_list - .iter() - .any(|api| endpoint.starts_with(api.as_str())) - }) - }) - .flatten_ok() - .collect::<Result<Vec<String>, _>>() - }) - } - pub(super) fn peers_and_heads_<DB: NetworkV1DbReadable>( - &self, - dunp_db: &DB, - ) -> KvResult<Vec<(PeerCardDbV1, Vec<DunpHeadDbV1>)>> { - Ok(dunp_db.peers_old().iter(.., |it| { - it.values() - .filter_map(|peer_res| { - if let Ok(peer) = peer_res { - if let Ok(pubkey) = PublicKey::from_base58(&peer.pubkey) { - let k_min = duniter_dbs::DunpNodeIdV1Db::new(0, pubkey); - let k_max = duniter_dbs::DunpNodeIdV1Db::new(u32::MAX, pubkey); - Some(( - peer, - dunp_db.heads_old().iter(k_min..k_max, |it| { - it.values().filter_map(|head| head.ok()).collect() - }), - )) - } else { - None - } - } else { - None - } - }) - .collect() - })) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use duniter_dbs::databases::network_v1::NetworkV1DbWritable; - use duniter_dbs::PeerCardDbV1; - - #[test] - fn test_empty_endpoints() -> KvResult<()> { - // Populate DB - let dunp_db = - duniter_dbs::databases::network_v1::NetworkV1Db::<Mem>::open(MemConf::default())?; - let db_reader = DbsReaderImpl::mem(); - let pk = PublicKey::default(); - - dunp_db - .peers_old_write() - .upsert(PubKeyKeyV2(pk), PeerCardDbV1::default())?; - - // Request Data - let api_list = vec!["GVA".to_owned()]; - assert_eq!( - db_reader.endpoints_(&dunp_db, api_list)?, - Vec::<String>::new() - ); - - Ok(()) - } - #[test] - fn test_endpoints_with_empty_api_list() -> KvResult<()> { - let dummy_endpoint = "GVA S domain.tld 443 gva"; - - // Populate DB - let dunp_db = - duniter_dbs::databases::network_v1::NetworkV1Db::<Mem>::open(MemConf::default())?; - let db_reader = DbsReaderImpl::mem(); - let pk = PublicKey::default(); - let peer = PeerCardDbV1 { - endpoints: vec![dummy_endpoint.to_owned()], - ..Default::default() - }; - - dunp_db.peers_old_write().upsert(PubKeyKeyV2(pk), peer)?; - - // Request Data - let api_list = vec![]; - assert_eq!( - db_reader.endpoints_(&dunp_db, api_list)?, - Vec::<String>::new() - ); - - Ok(()) - } - #[test] - fn test_single_peer_endpoints() -> KvResult<()> { - let dummy_endpoint = "GVA S domain.tld 443 gva"; - - // Populate DB - let dunp_db = - duniter_dbs::databases::network_v1::NetworkV1Db::<Mem>::open(MemConf::default())?; - let db_reader = DbsReaderImpl::mem(); - let pk = PublicKey::default(); - let peer = PeerCardDbV1 { - endpoints: vec![dummy_endpoint.to_owned()], - ..Default::default() - }; - - dunp_db.peers_old_write().upsert(PubKeyKeyV2(pk), peer)?; - - // Request Data - let api_list = vec!["GVA".to_owned()]; - assert_eq!( - db_reader.endpoints_(&dunp_db, api_list)?, - vec![dummy_endpoint.to_owned()] - ); - - Ok(()) - } - - #[test] - fn test_peers_and_heads() -> KvResult<()> { - let dunp_db = - duniter_dbs::databases::network_v1::NetworkV1Db::<Mem>::open(MemConf::default())?; - let db_reader = DbsReaderImpl::mem(); - let pk = PublicKey::default(); - - dunp_db.peers_old_write().upsert( - PubKeyKeyV2(pk), - PeerCardDbV1 { - pubkey: pk.to_string(), - ..Default::default() - }, - )?; - dunp_db.heads_old_write().upsert( - duniter_dbs::DunpNodeIdV1Db::new(42, pk), - DunpHeadDbV1::default(), - )?; - dunp_db.heads_old_write().upsert( - duniter_dbs::DunpNodeIdV1Db::new(43, pk), - DunpHeadDbV1 { - pubkey: PublicKey::from_base58("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - .expect("invalid pubkey"), - ..Default::default() - }, - )?; - - assert_eq!( - db_reader.peers_and_heads(&dunp_db)?, - vec![( - PeerCardDbV1 { - pubkey: pk.to_string(), - ..Default::default() - }, - vec![ - DunpHeadDbV1::default(), - DunpHeadDbV1 { - pubkey: PublicKey::from_base58("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - .expect("invalid pubkey"), - ..Default::default() - } - ] - )] - ); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/dbs-reader/src/pagination.rs b/rust-libs/modules/gva/dbs-reader/src/pagination.rs deleted file mode 100644 index 48d80bbc5..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/pagination.rs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Debug)] -pub struct PagedData<D: std::fmt::Debug> { - pub data: D, - pub has_previous_page: bool, - pub has_next_page: bool, -} -impl<D: std::fmt::Debug + Default> PagedData<D> { - pub fn empty() -> Self { - PagedData { - data: D::default(), - has_previous_page: false, - has_next_page: false, - } - } -} - -#[derive(Debug)] -pub struct PageInfo<T> { - pub(crate) pos: Option<T>, - /// Order: true for ASC, false for DESC - pub(crate) order: bool, - pub(crate) limit_opt: Option<NonZeroUsize>, -} -impl<T> PageInfo<T> { - pub fn new(pos: Option<T>, order: bool, limit_opt: Option<NonZeroUsize>) -> Self { - PageInfo { - pos, - order, - limit_opt, - } - } - pub fn limit_opt(&self) -> Option<NonZeroUsize> { - self.limit_opt - } - pub fn not_all(&self) -> bool { - self.limit_opt.is_some() || self.pos.is_some() - } - pub fn order(&self) -> bool { - self.order - } - pub fn pos(&self) -> Option<&T> { - self.pos.as_ref() - } -} -impl<T> Default for PageInfo<T> { - fn default() -> Self { - PageInfo { - pos: None, - order: true, - limit_opt: None, - } - } -} -impl<T> Clone for PageInfo<T> -where - T: Clone, -{ - fn clone(&self) -> Self { - Self { - pos: self.pos.clone(), - order: self.order, - limit_opt: self.limit_opt, - } - } -} -impl<T> Copy for PageInfo<T> where T: Copy {} - -pub(crate) fn has_next_page< - 'i, - C: 'static + std::fmt::Debug + Default + Ord, - I: DoubleEndedIterator<Item = OwnedOrRef<'i, C>>, ->( - mut page_cursors: I, - last_cursor_opt: Option<C>, - page_info: PageInfo<C>, - page_not_reversed: bool, -) -> bool { - if page_info.not_all() { - if let Some(last_cursor) = last_cursor_opt { - //println!("TMP last_cursor={:?}", last_cursor); - if let Some(page_end_cursor) = if page_not_reversed { - page_cursors.next_back() - } else { - page_cursors.next() - } { - //println!("TMP page_end_cursor={:?}", page_end_cursor); - page_end_cursor.as_ref() != &last_cursor - } else { - page_info.pos.unwrap_or_default() < last_cursor - } - } else { - false - } - } else { - false - } -} - -pub(crate) fn has_previous_page< - 'i, - C: 'static + std::fmt::Debug + Default + Ord, - I: DoubleEndedIterator<Item = OwnedOrRef<'i, C>>, ->( - mut page_cursors: I, - first_cursor_opt: Option<C>, - page_info: PageInfo<C>, - page_not_reversed: bool, -) -> bool { - if page_info.not_all() { - if let Some(first_cursor) = first_cursor_opt { - //println!("TMP first_cursor={:?}", first_cursor); - if let Some(page_start_cursor) = if page_not_reversed { - page_cursors.next() - } else { - page_cursors.next_back() - } { - page_start_cursor.as_ref() != &first_cursor - } else { - page_info.pos.unwrap_or_default() > first_cursor - } - } else { - false - } - } else { - false - } -} diff --git a/rust-libs/modules/gva/dbs-reader/src/txs_history.rs b/rust-libs/modules/gva/dbs-reader/src/txs_history.rs deleted file mode 100644 index 3a4e3c52a..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/txs_history.rs +++ /dev/null @@ -1,836 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use duniter_dbs::smallvec::SmallVec; -use duniter_gva_db::WalletHashWithBnV1Db; - -#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] -pub struct TxBcCursor { - pub block_number: BlockNumber, - pub tx_hash: Hash, -} -impl std::fmt::Display for TxBcCursor { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}:{}", self.block_number, self.tx_hash,) - } -} - -impl FromStr for TxBcCursor { - type Err = WrongCursor; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - let mut s = s.split(':'); - let block_number = s - .next() - .ok_or(WrongCursor)? - .parse() - .map_err(|_| WrongCursor)?; - let tx_hash = Hash::from_hex(s.next().ok_or(WrongCursor)?).map_err(|_| WrongCursor)?; - Ok(Self { - block_number, - tx_hash, - }) - } -} - -impl DbsReaderImpl { - pub(super) fn get_txs_history_bc_received_( - &self, - from: Option<u64>, - page_info: PageInfo<TxBcCursor>, - script_hash: Hash, - to: Option<u64>, - ) -> KvResult<PagedData<VecDeque<GvaTxDbV1>>> { - let mut start_k = WalletHashWithBnV1Db::new( - script_hash, - BlockNumber(if let Some(from) = from { - self.0 - .blocks_by_common_time() - .iter(U64BE(from).., |it| it) - .values() - .next_res()? - .unwrap_or(u32::MAX) - } else { - 0 - }), - ); - let mut end_k = WalletHashWithBnV1Db::new( - script_hash, - BlockNumber(if let Some(to) = to { - self.0 - .blocks_by_common_time() - .iter_rev(..U64BE(to), |it| it) - .values() - .next_res()? - .unwrap_or(0) - } else { - u32::MAX - }), - ); - let first_cursor_opt = if page_info.not_all() { - self.0 - .txs_by_recipient() - .iter_ref_slice(start_k..=end_k, |k, hashs| { - Ok(TxBcCursor { - block_number: BlockNumber(k.get_block_number()), - tx_hash: hashs[0], - }) - }) - .next_res()? - } else { - None - }; - let last_cursor_opt = if page_info.not_all() { - self.0 - .txs_by_recipient() - .iter_ref_slice_rev(start_k..=end_k, |k, hashs| { - Ok(TxBcCursor { - block_number: BlockNumber(k.get_block_number()), - tx_hash: hashs[hashs.len() - 1], - }) - }) - .next_res()? - } else { - None - }; - let first_hashs_opt = if let Some(TxBcCursor { - block_number, - tx_hash: hash_limit, - }) = page_info.pos - { - if page_info.order { - let hashs = self.0.txs_by_recipient().get_ref_slice( - &WalletHashWithBnV1Db::new(script_hash, block_number), - |hashs| { - Ok(hashs - .iter() - .rev() - .take_while(|hash| *hash != &hash_limit) - .copied() - .collect::<SmallVec<[Hash; 8]>>()) - }, - )?; - start_k = WalletHashWithBnV1Db::new(script_hash, BlockNumber(block_number.0 + 1)); - hashs - } else { - let hashs = self.0.txs_by_recipient().get_ref_slice( - &WalletHashWithBnV1Db::new(script_hash, block_number), - |hashs| { - Ok(hashs - .iter() - .take_while(|hash| *hash != &hash_limit) - .copied() - .collect::<SmallVec<[Hash; 8]>>()) - }, - )?; - if block_number == BlockNumber(0) { - return Ok(PagedData::empty()); - } - end_k = WalletHashWithBnV1Db::new(script_hash, BlockNumber(block_number.0 - 1)); - hashs - } - } else { - None - }; - - if page_info.order { - let txs_iter = self - .0 - .txs_by_recipient() - .iter_ref_slice(start_k..=end_k, |_k, hashs| { - let mut sent = SmallVec::<[GvaTxDbV1; 8]>::new(); - for hash in hashs { - if let Some(tx_db) = self.0.txs().get(HashKeyV2::from_ref(hash))? { - sent.push(tx_db); - } - } - Ok(sent) - }) - .flatten_ok(); - txs_history_bc_collect( - *self, - first_cursor_opt, - first_hashs_opt, - last_cursor_opt, - page_info, - txs_iter, - ) - } else { - let txs_iter = self - .0 - .txs_by_recipient() - .iter_ref_slice_rev(start_k..=end_k, |_k, hashs| { - let mut sent = SmallVec::<[GvaTxDbV1; 8]>::new(); - for hash in hashs.iter().rev() { - if let Some(tx_db) = self.0.txs().get(HashKeyV2::from_ref(hash))? { - sent.push(tx_db); - } - } - Ok(sent) - }) - .flatten_ok(); - txs_history_bc_collect( - *self, - first_cursor_opt, - first_hashs_opt, - last_cursor_opt, - page_info, - txs_iter, - ) - } - } - pub(super) fn get_txs_history_bc_sent_( - &self, - from: Option<u64>, - page_info: PageInfo<TxBcCursor>, - script_hash: Hash, - to: Option<u64>, - ) -> KvResult<PagedData<VecDeque<GvaTxDbV1>>> { - let mut start_k = WalletHashWithBnV1Db::new( - script_hash, - BlockNumber(if let Some(from) = from { - self.0 - .blocks_by_common_time() - .iter(U64BE(from).., |it| it) - .values() - .next_res()? - .unwrap_or(u32::MAX) - } else { - 0 - }), - ); - let mut end_k = WalletHashWithBnV1Db::new( - script_hash, - BlockNumber(if let Some(to) = to { - self.0 - .blocks_by_common_time() - .iter_rev(..U64BE(to), |it| it) - .values() - .next_res()? - .unwrap_or(0) - } else { - u32::MAX - }), - ); - let first_cursor_opt = if page_info.not_all() { - self.0 - .txs_by_issuer() - .iter_ref_slice(start_k..=end_k, |k, hashs| { - Ok(TxBcCursor { - block_number: BlockNumber(k.get_block_number()), - tx_hash: hashs[0], - }) - }) - .next_res()? - } else { - None - }; - let last_cursor_opt = if page_info.not_all() { - self.0 - .txs_by_issuer() - .iter_ref_slice_rev(start_k..=end_k, |k, hashs| { - Ok(TxBcCursor { - block_number: BlockNumber(k.get_block_number()), - tx_hash: hashs[hashs.len() - 1], - }) - }) - .next_res()? - } else { - None - }; - let first_hashs_opt = if let Some(TxBcCursor { - block_number, - tx_hash: hash_limit, - }) = page_info.pos - { - if page_info.order { - let hashs = self.0.txs_by_issuer().get_ref_slice( - &WalletHashWithBnV1Db::new(script_hash, block_number), - |hashs| { - Ok(hashs - .iter() - .rev() - .take_while(|hash| *hash != &hash_limit) - .copied() - .collect::<SmallVec<[Hash; 8]>>()) - }, - )?; - start_k = WalletHashWithBnV1Db::new(script_hash, BlockNumber(block_number.0 + 1)); - hashs - } else { - let hashs = self.0.txs_by_issuer().get_ref_slice( - &WalletHashWithBnV1Db::new(script_hash, block_number), - |hashs| { - Ok(hashs - .iter() - .take_while(|hash| *hash != &hash_limit) - .copied() - .collect::<SmallVec<[Hash; 8]>>()) - }, - )?; - if block_number == BlockNumber(0) { - return Ok(PagedData::empty()); - } - end_k = WalletHashWithBnV1Db::new(script_hash, BlockNumber(block_number.0 - 1)); - hashs - } - } else { - None - }; - - if page_info.order { - let txs_iter = self - .0 - .txs_by_issuer() - .iter_ref_slice(start_k..=end_k, |_k, hashs| { - let mut sent = SmallVec::<[GvaTxDbV1; 8]>::new(); - for hash in hashs { - if let Some(tx_db) = self.0.txs().get(HashKeyV2::from_ref(hash))? { - sent.push(tx_db); - } - } - Ok(sent) - }) - .flatten_ok(); - txs_history_bc_collect( - *self, - first_cursor_opt, - first_hashs_opt, - last_cursor_opt, - page_info, - txs_iter, - ) - } else { - let txs_iter = self - .0 - .txs_by_issuer() - .iter_ref_slice_rev(start_k..=end_k, |_k, hashs| { - let mut sent = SmallVec::<[GvaTxDbV1; 8]>::new(); - for hash in hashs.iter().rev() { - if let Some(tx_db) = self.0.txs().get(HashKeyV2::from_ref(hash))? { - sent.push(tx_db); - } - } - Ok(sent) - }) - .flatten_ok(); - txs_history_bc_collect( - *self, - first_cursor_opt, - first_hashs_opt, - last_cursor_opt, - page_info, - txs_iter, - ) - } - } - pub(super) fn get_txs_history_mempool_<TxsMpDb: 'static + TxsMpV2DbReadable>( - &self, - txs_mp_db_ro: &TxsMpDb, - pubkey: PublicKey, - ) -> KvResult<(Vec<TransactionDocumentV10>, Vec<TransactionDocumentV10>)> { - let sending = txs_mp_db_ro - .txs_by_issuer() - .get_ref_slice(&PubKeyKeyV2(pubkey), |hashs| { - let mut sent = Vec::with_capacity(hashs.len()); - for hash in hashs { - if let Some(tx_db) = txs_mp_db_ro.txs().get(HashKeyV2::from_ref(hash))? { - sent.push(tx_db.0); - } - } - Ok(sent) - })? - .unwrap_or_default(); - let pending = txs_mp_db_ro - .txs_by_recipient() - .get_ref_slice(&PubKeyKeyV2(pubkey), |hashs| { - let mut pending = Vec::with_capacity(hashs.len()); - for hash in hashs { - if let Some(tx_db) = txs_mp_db_ro.txs().get(HashKeyV2::from_ref(hash))? { - pending.push(tx_db.0); - } - } - Ok(pending) - })? - .unwrap_or_default(); - Ok((sending, pending)) - } -} - -fn txs_history_bc_collect<I: Iterator<Item = KvResult<GvaTxDbV1>>>( - dbs_reader: DbsReaderImpl, - first_cursor_opt: Option<TxBcCursor>, - first_hashs_opt: Option<SmallVec<[Hash; 8]>>, - last_cursor_opt: Option<TxBcCursor>, - page_info: PageInfo<TxBcCursor>, - txs_iter: I, -) -> KvResult<PagedData<VecDeque<GvaTxDbV1>>> { - let mut txs = if let Some(limit) = page_info.limit_opt { - txs_iter - .take(limit.get()) - .collect::<KvResult<VecDeque<_>>>()? - } else { - txs_iter.collect::<KvResult<VecDeque<_>>>()? - }; - - if let Some(first_hashs) = first_hashs_opt { - for hash in first_hashs.into_iter() { - if let Some(tx_db) = dbs_reader.0.txs().get(&HashKeyV2(hash))? { - txs.push_front(tx_db); - } - } - } - - Ok(PagedData { - has_next_page: if page_info.order { - has_next_page( - txs.iter().map(|tx_db| { - TxBcCursor { - block_number: tx_db.written_block.number, - tx_hash: tx_db.tx.get_hash(), - } - .into() - }), - last_cursor_opt, - page_info, - page_info.order, - ) - } else { - // Server can't efficiently determine hasNextPage in DESC order - false - }, - has_previous_page: if page_info.order { - // Server can't efficiently determine hasPreviousPage in ASC order - false - } else { - has_previous_page( - txs.iter().map(|tx_db| { - TxBcCursor { - block_number: tx_db.written_block.number, - tx_hash: tx_db.tx.get_hash(), - } - .into() - }), - first_cursor_opt, - page_info, - page_info.order, - ) - }, - data: txs, - }) -} - -// Needed for BMA only -pub struct TxsHistory { - pub sent: Vec<GvaTxDbV1>, - pub received: Vec<GvaTxDbV1>, - pub sending: Vec<TransactionDocumentV10>, - pub pending: Vec<TransactionDocumentV10>, -} - -// Needed for BMA only -pub fn get_transactions_history_for_bma<GvaDb: GvaV1DbReadable, TxsMpDb: TxsMpV2DbReadable>( - gva_db_ro: &GvaDb, - txs_mp_db_ro: &TxsMpDb, - pubkey: PublicKey, -) -> KvResult<TxsHistory> { - let script_hash = Hash::compute(WalletScriptV10::single_sig(pubkey).to_string().as_bytes()); - let start_k = WalletHashWithBnV1Db::new(script_hash, BlockNumber(0)); - let end_k = WalletHashWithBnV1Db::new(script_hash, BlockNumber(u32::MAX)); - - let sent = gva_db_ro - .txs_by_issuer() - .iter_ref_slice(start_k..end_k, |_k, hashs| { - let mut sent = SmallVec::<[GvaTxDbV1; 2]>::new(); - for hash in hashs { - if let Some(tx_db) = gva_db_ro.txs().get(HashKeyV2::from_ref(hash))? { - sent.push(tx_db); - } - } - Ok(sent) - }) - .flatten_ok() - .collect::<KvResult<Vec<_>>>()?; - - let received = gva_db_ro - .txs_by_recipient() - .iter_ref_slice(start_k..end_k, |_k, hashs| { - let mut sent = SmallVec::<[GvaTxDbV1; 2]>::new(); - for hash in hashs { - if let Some(tx_db) = gva_db_ro.txs().get(HashKeyV2::from_ref(hash))? { - sent.push(tx_db); - } - } - Ok(sent) - }) - .flatten_ok() - .collect::<KvResult<Vec<_>>>()?; - let sending = txs_mp_db_ro - .txs_by_issuer() - .get_ref_slice(&PubKeyKeyV2(pubkey), |hashs| { - let mut sent = Vec::with_capacity(hashs.len()); - for hash in hashs { - if let Some(tx_db) = txs_mp_db_ro.txs().get(HashKeyV2::from_ref(hash))? { - sent.push(tx_db.0); - } - } - Ok(sent) - })? - .unwrap_or_default(); - let pending = txs_mp_db_ro - .txs_by_recipient() - .get_ref_slice(&PubKeyKeyV2(pubkey), |hashs| { - let mut pending = Vec::with_capacity(hashs.len()); - for hash in hashs { - if let Some(tx_db) = txs_mp_db_ro.txs().get(HashKeyV2::from_ref(hash))? { - pending.push(tx_db.0); - } - } - Ok(pending) - })? - .unwrap_or_default(); - Ok(TxsHistory { - sent, - received, - sending, - pending, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use dubp::{ - common::prelude::{BlockHash, Blockstamp}, - crypto::keys::ed25519::PublicKey, - documents::transaction::{TransactionDocumentV10, TransactionDocumentV10Stringified}, - documents_parser::prelude::FromStringObject, - }; - use duniter_gva_db::GvaV1DbWritable; - use maplit::btreeset; - use unwrap::unwrap; - - fn gen_tx(hash: Hash, written_block_number: BlockNumber) -> GvaTxDbV1 { - GvaTxDbV1 { - tx: unwrap!(TransactionDocumentV10::from_string_object( - &TransactionDocumentV10Stringified { - currency: "test".to_owned(), - blockstamp: - "1-0000000000000000000000000000000000000000000000000000000000000000" - .to_owned(), - locktime: 0, - issuers: vec![], - inputs: vec![], - unlocks: vec![], - outputs: vec![], - comment: "".to_owned(), - signatures: vec![], - hash: Some(hash.to_hex()), - } - )), - written_block: Blockstamp { - number: written_block_number, - hash: BlockHash(Hash::default()), - }, - written_time: 1, - } - } - - #[test] - fn test_get_txs_history_bc_received() -> KvResult<()> { - let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?; - let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) }); - - let s1 = WalletScriptV10::single_sig(PublicKey::default()); - let s1_hash = Hash::compute(&s1.to_string().as_bytes()); - - gva_db.txs_write().upsert( - HashKeyV2(Hash::default()), - gen_tx(Hash::default(), BlockNumber(1)), - )?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([1; 32])), - gen_tx(Hash([1; 32]), BlockNumber(1)), - )?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([2; 32])), - gen_tx(Hash([2; 32]), BlockNumber(1)), - )?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([3; 32])), - gen_tx(Hash([3; 32]), BlockNumber(1)), - )?; - gva_db.txs_by_recipient_write().upsert( - WalletHashWithBnV1Db::new(s1_hash, BlockNumber(1)), - btreeset![Hash::default(), Hash([1; 32]), Hash([2; 32]), Hash([3; 32])], - )?; - gva_db.blocks_by_common_time_write().upsert(U64BE(1), 1)?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([4; 32])), - gen_tx(Hash([4; 32]), BlockNumber(2)), - )?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([5; 32])), - gen_tx(Hash([5; 32]), BlockNumber(2)), - )?; - gva_db.txs_by_recipient_write().upsert( - WalletHashWithBnV1Db::new(s1_hash, BlockNumber(2)), - btreeset![Hash([4; 32]), Hash([5; 32])], - )?; - gva_db.blocks_by_common_time_write().upsert(U64BE(2), 2)?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([6; 32])), - gen_tx(Hash([6; 32]), BlockNumber(3)), - )?; - gva_db.txs_by_recipient_write().upsert( - WalletHashWithBnV1Db::new(s1_hash, BlockNumber(3)), - btreeset![Hash([6; 32])], - )?; - gva_db.blocks_by_common_time_write().upsert(U64BE(3), 3)?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([7; 32])), - gen_tx(Hash([7; 32]), BlockNumber(4)), - )?; - gva_db.txs_by_recipient_write().upsert( - WalletHashWithBnV1Db::new(s1_hash, BlockNumber(4)), - btreeset![Hash([7; 32])], - )?; - gva_db.blocks_by_common_time_write().upsert(U64BE(4), 4)?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([8; 32])), - gen_tx(Hash([8; 32]), BlockNumber(5)), - )?; - gva_db.txs_by_recipient_write().upsert( - WalletHashWithBnV1Db::new(s1_hash, BlockNumber(5)), - btreeset![Hash([8; 32])], - )?; - gva_db.blocks_by_common_time_write().upsert(U64BE(5), 5)?; - - /*let received = db_reader.get_txs_history_bc_received( - PageInfo { - order: true, - limit_opt: None, - pos: Some(TxBcCursor { - tx_hash: Hash([1; 32]), - block_number: BlockNumber(1), - }), - }, - s1_hash, - )?; - assert_eq!( - received.data - .into_iter() - .map(|tx_db| tx_db.tx.get_hash()) - .collect::<Vec<_>>(), - vec![Hash([2; 32]), Hash([3; 32]), Hash([4; 32]), Hash([5; 32])], - ); - assert!(!received.has_next_page); - assert!(!received.has_previous_page); - - let received = db_reader.get_txs_history_bc_received( - PageInfo { - order: false, - limit_opt: None, - pos: Some(TxBcCursor { - tx_hash: Hash([1; 32]), - block_number: BlockNumber(1), - }), - }, - s1_hash, - )?; - assert_eq!( - received.data - .into_iter() - .map(|tx_db| tx_db.tx.get_hash()) - .collect::<Vec<_>>(), - vec![Hash([0; 32])], - ); - assert!(!received.has_next_page); - assert!(!received.has_previous_page);*/ - - let received = db_reader.get_txs_history_bc_received( - None, - PageInfo { - order: false, - limit_opt: None, - pos: Some(TxBcCursor { - tx_hash: Hash([5; 32]), - block_number: BlockNumber(2), - }), - }, - s1_hash, - None, - )?; - assert_eq!( - received - .data - .into_iter() - .map(|tx_db| tx_db.tx.get_hash()) - .collect::<Vec<_>>(), - vec![ - Hash([4; 32]), - Hash([3; 32]), - Hash([2; 32]), - Hash([1; 32]), - Hash([0; 32]), - ], - ); - assert!(!received.has_next_page); - assert!(!received.has_previous_page); - - let received = db_reader.get_txs_history_bc_received( - Some(2), - PageInfo { - order: true, - limit_opt: None, - pos: None, - }, - s1_hash, - Some(5), - )?; - assert_eq!( - received - .data - .into_iter() - .map(|tx_db| tx_db.tx.get_hash()) - .collect::<Vec<_>>(), - vec![Hash([4; 32]), Hash([5; 32]), Hash([6; 32]), Hash([7; 32])], - ); - assert!(!received.has_next_page); - assert!(!received.has_previous_page); - - Ok(()) - } - - #[test] - fn test_get_txs_history_bc_sent() -> KvResult<()> { - let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?; - let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) }); - - let s1 = WalletScriptV10::single_sig(PublicKey::default()); - let s1_hash = Hash::compute(&s1.to_string().as_bytes()); - - gva_db.txs_write().upsert( - HashKeyV2(Hash::default()), - gen_tx(Hash::default(), BlockNumber(1)), - )?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([1; 32])), - gen_tx(Hash([1; 32]), BlockNumber(1)), - )?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([2; 32])), - gen_tx(Hash([2; 32]), BlockNumber(1)), - )?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([3; 32])), - gen_tx(Hash([3; 32]), BlockNumber(1)), - )?; - gva_db.txs_by_issuer_write().upsert( - WalletHashWithBnV1Db::new(s1_hash, BlockNumber(1)), - btreeset![Hash::default(), Hash([1; 32]), Hash([2; 32]), Hash([3; 32])], - )?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([4; 32])), - gen_tx(Hash([4; 32]), BlockNumber(2)), - )?; - gva_db.txs_write().upsert( - HashKeyV2(Hash([5; 32])), - gen_tx(Hash([5; 32]), BlockNumber(2)), - )?; - gva_db.txs_by_issuer_write().upsert( - WalletHashWithBnV1Db::new(s1_hash, BlockNumber(2)), - btreeset![Hash([4; 32]), Hash([5; 32])], - )?; - - let sent = db_reader.get_txs_history_bc_sent( - None, - PageInfo { - order: true, - limit_opt: None, - pos: Some(TxBcCursor { - tx_hash: Hash([1; 32]), - block_number: BlockNumber(1), - }), - }, - s1_hash, - None, - )?; - assert_eq!( - sent.data - .into_iter() - .map(|tx_db| tx_db.tx.get_hash()) - .collect::<Vec<_>>(), - vec![Hash([2; 32]), Hash([3; 32]), Hash([4; 32]), Hash([5; 32])], - ); - assert!(!sent.has_next_page); - assert!(!sent.has_previous_page); - - let sent = db_reader.get_txs_history_bc_sent( - None, - PageInfo { - order: false, - limit_opt: None, - pos: Some(TxBcCursor { - tx_hash: Hash([1; 32]), - block_number: BlockNumber(1), - }), - }, - s1_hash, - None, - )?; - assert_eq!( - sent.data - .into_iter() - .map(|tx_db| tx_db.tx.get_hash()) - .collect::<Vec<_>>(), - vec![Hash([0; 32])], - ); - assert!(!sent.has_next_page); - assert!(!sent.has_previous_page); - - let sent = db_reader.get_txs_history_bc_sent( - None, - PageInfo { - order: false, - limit_opt: None, - pos: Some(TxBcCursor { - tx_hash: Hash([5; 32]), - block_number: BlockNumber(2), - }), - }, - s1_hash, - None, - )?; - assert_eq!( - sent.data - .into_iter() - .map(|tx_db| tx_db.tx.get_hash()) - .collect::<Vec<_>>(), - vec![ - Hash([4; 32]), - Hash([3; 32]), - Hash([2; 32]), - Hash([1; 32]), - Hash([0; 32]), - ], - ); - assert!(!sent.has_next_page); - assert!(!sent.has_previous_page); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/dbs-reader/src/uds_of_pubkey.rs b/rust-libs/modules/gva/dbs-reader/src/uds_of_pubkey.rs deleted file mode 100644 index 8ae09a58d..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/uds_of_pubkey.rs +++ /dev/null @@ -1,829 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use duniter_dbs::smallvec::SmallVec; -use duniter_dbs::{ - databases::bc_v2::{UdsEvent, UdsRevalEvent}, - UdIdV2, -}; - -#[derive(Debug, Default)] -pub struct UdsWithSum { - pub uds: Vec<(BlockNumber, SourceAmount)>, - pub sum: SourceAmount, -} - -impl DbsReaderImpl { - pub(super) fn all_uds_of_pubkey_( - &self, - bc_db: &BcV2DbRo<FileBackend>, - pubkey: PublicKey, - page_info: PageInfo<BlockNumber>, - ) -> KvResult<PagedData<UdsWithSum>> { - ( - bc_db.uds_reval(), - self.0.blocks_with_ud(), - self.0.gva_identities(), - ) - .read(|(uds_reval, blocks_with_ud, gva_identities)| { - if let Some(gva_idty) = gva_identities.get(&PubKeyKeyV2(pubkey))? { - match page_info.pos { - None => { - if page_info.order { - blocks_with_ud.iter(.., move |it| { - all_uds_of_pubkey_inner::<FileBackend, _>( - gva_idty, - page_info, - it.keys().map_ok(|bn| BlockNumber(bn.0)), - uds_reval, - None, - ) - }) - } else { - let last_ud_opt = - blocks_with_ud.iter_rev(.., |it| it.keys().next_res())?; - blocks_with_ud.iter_rev(.., move |it| { - all_uds_of_pubkey_inner::<FileBackend, _>( - gva_idty, - page_info, - it.keys().map_ok(|bn| BlockNumber(bn.0)), - uds_reval, - last_ud_opt.map(|bn| BlockNumber(bn.0)), - ) - }) - } - } - Some(pos) => { - if page_info.order { - blocks_with_ud.iter(U32BE(pos.0).., move |it| { - all_uds_of_pubkey_inner::<FileBackend, _>( - gva_idty, - page_info, - it.keys().map_ok(|bn| BlockNumber(bn.0)), - uds_reval, - None, - ) - }) - } else { - let last_ud_opt = - blocks_with_ud.iter_rev(.., |it| it.keys().next_res())?; - blocks_with_ud.iter_rev(..=U32BE(pos.0), move |it| { - all_uds_of_pubkey_inner::<FileBackend, _>( - gva_idty, - page_info, - it.keys().map_ok(|bn| BlockNumber(bn.0)), - uds_reval, - last_ud_opt.map(|bn| BlockNumber(bn.0)), - ) - }) - } - } - } - } else { - Ok(PagedData::empty()) - } - }) - } - - pub(super) fn unspent_uds_of_pubkey_( - &self, - bc_db: &BcV2DbRo<FileBackend>, - pubkey: PublicKey, - page_info: PageInfo<BlockNumber>, - bn_to_exclude_opt: Option<&BTreeSet<BlockNumber>>, - amount_target_opt: Option<SourceAmount>, - ) -> KvResult<PagedData<UdsWithSum>> { - (bc_db.uds(), bc_db.uds_reval()).read(|(uds, uds_reval)| { - let (first_ud_opt, last_ud_opt) = if page_info.not_all() { - get_first_and_last_unspent_ud(&uds, pubkey, bn_to_exclude_opt)? - } else { - (None, None) - }; - let mut blocks_numbers = if let Some(pos) = page_info.pos { - if page_info.order { - uds.iter( - UdIdV2(pubkey, pos)..UdIdV2(pubkey, BlockNumber(u32::MAX)), - |it| { - let it = it.keys().map_ok(|UdIdV2(_p, bn)| bn); - if let Some(bn_to_exclude) = bn_to_exclude_opt { - it.filter_ok(|bn| !bn_to_exclude.contains(&bn)) - .collect::<KvResult<Vec<_>>>() - } else { - it.collect::<KvResult<Vec<_>>>() - } - }, - )? - } else { - uds.iter_rev(UdIdV2(pubkey, BlockNumber(0))..=UdIdV2(pubkey, pos), |it| { - let it = it.keys().map_ok(|UdIdV2(_p, bn)| bn); - if let Some(bn_to_exclude) = bn_to_exclude_opt { - it.filter_ok(|bn| !bn_to_exclude.contains(&bn)) - .collect::<KvResult<Vec<_>>>() - } else { - it.collect::<KvResult<Vec<_>>>() - } - })? - } - } else if page_info.order { - uds.iter( - UdIdV2(pubkey, BlockNumber(0))..UdIdV2(pubkey, BlockNumber(u32::MAX)), - |it| { - let it = it.keys().map_ok(|UdIdV2(_p, bn)| bn); - if let Some(bn_to_exclude) = bn_to_exclude_opt { - it.filter_ok(|bn| !bn_to_exclude.contains(&bn)) - .collect::<KvResult<Vec<_>>>() - } else { - it.collect::<KvResult<Vec<_>>>() - } - }, - )? - } else { - uds.iter_rev( - UdIdV2(pubkey, BlockNumber(0))..UdIdV2(pubkey, BlockNumber(u32::MAX)), - |it| { - let it = it.keys().map_ok(|UdIdV2(_p, bn)| bn); - if let Some(bn_to_exclude) = bn_to_exclude_opt { - it.filter_ok(|bn| !bn_to_exclude.contains(&bn)) - .collect::<KvResult<Vec<_>>>() - } else { - it.collect::<KvResult<Vec<_>>>() - } - }, - )? - }; - - if blocks_numbers.is_empty() { - Ok(PagedData::empty()) - } else { - if let Some(limit) = page_info.limit_opt { - blocks_numbers.truncate(limit.get()); - } - let first_block_number = if page_info.order { - blocks_numbers[0] - } else { - blocks_numbers[blocks_numbers.len() - 1] - }; - let first_reval = uds_reval - .iter_rev(..=U32BE(first_block_number.0), |it| it.keys().next_res())? - .expect("corrupted db"); - let blocks_numbers_len = blocks_numbers.len(); - let blocks_numbers = blocks_numbers.into_iter(); - let uds_with_sum = if page_info.order { - collect_uds( - blocks_numbers, - blocks_numbers_len, - first_reval, - uds_reval, - amount_target_opt, - )? - } else { - collect_uds( - blocks_numbers.rev(), - blocks_numbers_len, - first_reval, - uds_reval, - amount_target_opt, - )? - }; - Ok(PagedData { - has_previous_page: has_previous_page( - uds_with_sum.uds.iter().map(|(bn, _sa)| bn.into()), - first_ud_opt, - page_info, - true, - ), - has_next_page: has_next_page( - uds_with_sum.uds.iter().map(|(bn, _sa)| bn.into()), - last_ud_opt, - page_info, - true, - ), - data: uds_with_sum, - }) - } - }) - } -} - -fn all_uds_of_pubkey_inner<B, I>( - gva_idty: GvaIdtyDbV1, - page_info: PageInfo<BlockNumber>, - blocks_with_ud: I, - uds_reval: TxColRo<B::Col, UdsRevalEvent>, - last_ud_opt: Option<BlockNumber>, -) -> KvResult<PagedData<UdsWithSum>> -where - B: Backend, - I: Iterator<Item = KvResult<BlockNumber>>, -{ - let first_ud = gva_idty.first_ud; - let mut blocks_numbers = filter_blocks_numbers(gva_idty, page_info, blocks_with_ud)?; - - if blocks_numbers.is_empty() { - return Ok(PagedData::empty()); - } - - let not_reach_end = if page_info.order { - if let Some(limit) = page_info.limit_opt { - if blocks_numbers.len() <= limit.get() { - false - } else { - blocks_numbers.pop(); - true - } - } else { - false - } - } else if let Some(last_ud) = last_ud_opt { - blocks_numbers[0] != last_ud - } else { - false - }; - let blocks_numbers_len = blocks_numbers.len(); - - let first_block_number = if page_info.order { - blocks_numbers[0] - } else { - blocks_numbers[blocks_numbers_len - 1] - }; - - let first_reval = uds_reval - .iter_rev(..=U32BE(first_block_number.0), |it| it.keys().next_res())? - .expect("corrupted db"); - - let uds_with_sum = if page_info.order { - collect_uds( - blocks_numbers.into_iter(), - blocks_numbers_len, - first_reval, - uds_reval, - None, - )? - } else { - collect_uds( - blocks_numbers.into_iter().rev(), - blocks_numbers_len, - first_reval, - uds_reval, - None, - )? - }; - - Ok(PagedData { - has_previous_page: has_previous_page( - uds_with_sum.uds.iter().map(|(bn, _sa)| bn.into()), - first_ud, - page_info, - true, - ), - has_next_page: not_reach_end, - data: uds_with_sum, - }) -} - -fn filter_blocks_numbers<I: Iterator<Item = KvResult<BlockNumber>>>( - gva_idty: GvaIdtyDbV1, - page_info: PageInfo<BlockNumber>, - blocks_with_ud: I, -) -> KvResult<Vec<BlockNumber>> { - let mut is_member_changes = SmallVec::<[BlockNumber; 4]>::new(); - for (join, leave) in gva_idty.joins.iter().zip(gva_idty.leaves.iter()) { - is_member_changes.push(*join); - is_member_changes.push(*leave); - } - if gva_idty.joins.len() > gva_idty.leaves.len() { - is_member_changes.push(*gva_idty.joins.last().unwrap_or_else(|| unreachable!())); - } - - if page_info.order { - let mut i = 0; - let mut is_member = false; - if let Some(limit) = page_info.limit_opt { - blocks_with_ud - .filter_ok(|bn| { - while i < is_member_changes.len() && *bn >= is_member_changes[i] { - is_member = !is_member; - i += 1; - } - is_member - }) - .take(limit.get() + 1) - .collect::<KvResult<Vec<_>>>() - } else { - blocks_with_ud - .filter_ok(|bn| { - while i < is_member_changes.len() && *bn >= is_member_changes[i] { - is_member = !is_member; - i += 1; - } - is_member - }) - .collect::<KvResult<Vec<_>>>() - } - } else { - let is_member_changes: SmallVec<[BlockNumber; 4]> = - is_member_changes.into_iter().rev().collect(); - let mut i = 0; - let mut is_member = gva_idty.is_member; - if let Some(limit) = page_info.limit_opt { - blocks_with_ud - .filter_ok(|bn| { - /*println!( - "TMP (bn, is_member_changes[{}])=({}, {})", - i, bn, is_member_changes[i] - );*/ - while i < is_member_changes.len() && *bn < is_member_changes[i] { - is_member = !is_member; - i += 1; - } - is_member - }) - .take(limit.get()) - .collect::<KvResult<Vec<_>>>() - } else { - blocks_with_ud - .filter_ok(|bn| { - while i < is_member_changes.len() && *bn < is_member_changes[i] { - is_member = !is_member; - i += 1; - } - is_member - }) - .collect::<KvResult<Vec<_>>>() - } - } -} - -fn get_first_and_last_unspent_ud<BC: BackendCol>( - uds: &TxColRo<BC, UdsEvent>, - pubkey: PublicKey, - bn_to_exclude_opt: Option<&BTreeSet<BlockNumber>>, -) -> KvResult<(Option<BlockNumber>, Option<BlockNumber>)> { - if let Some(bn_to_exclude) = bn_to_exclude_opt { - Ok(( - uds.iter( - UdIdV2(pubkey, BlockNumber(0))..UdIdV2(pubkey, BlockNumber(u32::MAX)), - |it| { - it.keys() - .filter_map_ok(|UdIdV2(_p, bn)| { - if !bn_to_exclude.contains(&bn) { - Some(bn) - } else { - None - } - }) - .next_res() - }, - )?, - uds.iter_rev( - UdIdV2(pubkey, BlockNumber(0))..UdIdV2(pubkey, BlockNumber(u32::MAX)), - |it| { - it.keys() - .filter_map_ok(|UdIdV2(_p, bn)| { - if !bn_to_exclude.contains(&bn) { - Some(bn) - } else { - None - } - }) - .next_res() - }, - )?, - )) - } else { - Ok(( - uds.iter( - UdIdV2(pubkey, BlockNumber(0))..UdIdV2(pubkey, BlockNumber(u32::MAX)), - |it| it.keys().map_ok(|UdIdV2(_p, bn)| bn).next_res(), - )?, - uds.iter_rev( - UdIdV2(pubkey, BlockNumber(0))..UdIdV2(pubkey, BlockNumber(u32::MAX)), - |it| it.keys().map_ok(|UdIdV2(_p, bn)| bn).next_res(), - )?, - )) - } -} - -macro_rules! collect_one_ud { - ($block_number:ident, $current_ud:ident, $uds:ident, $sum:ident, $amount_target_opt:ident) => { - $uds.push(($block_number, $current_ud)); - $sum = $sum + $current_ud; - if let Some(amount_target) = $amount_target_opt { - if $sum >= amount_target { - return Ok(UdsWithSum { $uds, $sum }); - } - } - }; -} - -fn collect_uds<BC: BackendCol, I: Iterator<Item = BlockNumber>>( - mut blocks_numbers: I, - blocks_numbers_len: usize, - first_reval: U32BE, - uds_reval: TxColRo<BC, UdsRevalEvent>, - amount_opt: Option<SourceAmount>, -) -> KvResult<UdsWithSum> { - let uds_revals = uds_reval.iter(first_reval.., |it| it.collect::<KvResult<Vec<_>>>())?; - - if uds_revals.is_empty() { - Ok(UdsWithSum::default()) - } else { - let mut current_ud = (uds_revals[0].1).0; - let mut uds = Vec::with_capacity(blocks_numbers_len); - let mut sum = SourceAmount::ZERO; - - // Uds before last reval - for (block_reval, amount_reval) in &uds_revals[1..] { - 'blocks_numbers: while let Some(block_number) = blocks_numbers.next() { - if block_number.0 >= block_reval.0 { - current_ud = amount_reval.0; - collect_one_ud!(block_number, current_ud, uds, sum, amount_opt); - break 'blocks_numbers; - } else { - collect_one_ud!(block_number, current_ud, uds, sum, amount_opt); - } - } - } - - // Uds after last reval - for block_number in blocks_numbers { - collect_one_ud!(block_number, current_ud, uds, sum, amount_opt); - } - - Ok(UdsWithSum { uds, sum }) - } -} - -#[cfg(test)] -mod tests { - - use super::*; - use duniter_dbs::smallvec::smallvec as svec; - use duniter_dbs::{databases::bc_v2::BcV2DbWritable, SourceAmountValV2, UdIdV2}; - use duniter_gva_db::GvaV1DbWritable; - - #[test] - fn test_filter_blocks_numbers() -> KvResult<()> { - let idty = GvaIdtyDbV1 { - is_member: true, - joins: svec![BlockNumber(26), BlockNumber(51)], - leaves: [BlockNumber(32)].iter().copied().collect(), - first_ud: Some(BlockNumber(29)), - }; - let blocks_with_ud = vec![ - BlockNumber(3), - BlockNumber(9), - BlockNumber(15), - BlockNumber(22), - BlockNumber(29), - BlockNumber(35), - BlockNumber(42), - BlockNumber(48), - BlockNumber(54), - BlockNumber(60), - ]; - - assert_eq!( - filter_blocks_numbers( - idty.clone(), - PageInfo { - pos: None, - order: true, - limit_opt: NonZeroUsize::new(1), - }, - blocks_with_ud.iter().copied().map(Ok), - )?, - vec![BlockNumber(29), BlockNumber(54)] - ); - assert_eq!( - filter_blocks_numbers( - idty, - PageInfo { - pos: None, - order: false, - limit_opt: None, - }, - blocks_with_ud.into_iter().rev().map(Ok), - )?, - vec![BlockNumber(60), BlockNumber(54), BlockNumber(29)] - ); - Ok(()) - } - - #[test] - fn test_all_uds_of_pubkey() -> KvResult<()> { - let pk = PublicKey::default(); - let idty = GvaIdtyDbV1 { - is_member: true, - joins: svec![BlockNumber(26), BlockNumber(51)], - leaves: [BlockNumber(32)].iter().copied().collect(), - first_ud: Some(BlockNumber(29)), - }; - - let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?; - let bc_db_ro = bc_db.get_ro_handler(); - let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?; - let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) }); - bc_db - .uds_reval_write() - .upsert(U32BE(0), SourceAmountValV2(SourceAmount::with_base0(10)))?; - bc_db - .uds_reval_write() - .upsert(U32BE(40), SourceAmountValV2(SourceAmount::with_base0(12)))?; - gva_db - .gva_identities_write() - .upsert(PubKeyKeyV2(pk), idty)?; - gva_db.blocks_with_ud_write().upsert(U32BE(22), ())?; - gva_db.blocks_with_ud_write().upsert(U32BE(29), ())?; - gva_db.blocks_with_ud_write().upsert(U32BE(35), ())?; - gva_db.blocks_with_ud_write().upsert(U32BE(42), ())?; - gva_db.blocks_with_ud_write().upsert(U32BE(48), ())?; - gva_db.blocks_with_ud_write().upsert(U32BE(54), ())?; - gva_db.blocks_with_ud_write().upsert(U32BE(60), ())?; - - // Get all uds - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = db_reader.all_uds_of_pubkey(&bc_db_ro, pk, PageInfo::default())?; - assert_eq!( - uds, - vec![ - (BlockNumber(29), SourceAmount::with_base0(10)), - (BlockNumber(54), SourceAmount::with_base0(12)), - (BlockNumber(60), SourceAmount::with_base0(12)), - ] - ); - assert_eq!(sum, SourceAmount::with_base0(34)); - assert!(!has_previous_page); - assert!(!has_next_page); - - // Get all uds with limit - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = db_reader.all_uds_of_pubkey( - &bc_db_ro, - pk, - PageInfo { - limit_opt: NonZeroUsize::new(2), - ..Default::default() - }, - )?; - assert_eq!( - uds, - vec![ - (BlockNumber(29), SourceAmount::with_base0(10)), - (BlockNumber(54), SourceAmount::with_base0(12)), - ] - ); - assert_eq!(sum, SourceAmount::with_base0(22)); - assert!(!has_previous_page); - assert!(has_next_page); - - // Get all uds from particular position - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = db_reader.all_uds_of_pubkey( - &bc_db_ro, - pk, - PageInfo { - pos: Some(BlockNumber(50)), - ..Default::default() - }, - )?; - assert_eq!( - uds, - vec![ - (BlockNumber(54), SourceAmount::with_base0(12)), - (BlockNumber(60), SourceAmount::with_base0(12)), - ] - ); - assert_eq!(sum, SourceAmount::with_base0(24)); - assert!(has_previous_page); - assert!(!has_next_page); - - // Get all uds on DESC order - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = db_reader.all_uds_of_pubkey( - &bc_db_ro, - pk, - PageInfo { - order: false, - ..Default::default() - }, - )?; - assert_eq!( - uds, - vec![ - (BlockNumber(29), SourceAmount::with_base0(10)), - (BlockNumber(54), SourceAmount::with_base0(12)), - (BlockNumber(60), SourceAmount::with_base0(12)), - ] - ); - assert_eq!(sum, SourceAmount::with_base0(34)); - assert!(!has_previous_page); - assert!(!has_next_page); - - // Get all uds on DESC order with limit - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = db_reader.all_uds_of_pubkey( - &bc_db_ro, - pk, - PageInfo { - order: false, - limit_opt: NonZeroUsize::new(2), - ..Default::default() - }, - )?; - assert_eq!( - uds, - vec![ - (BlockNumber(54), SourceAmount::with_base0(12)), - (BlockNumber(60), SourceAmount::with_base0(12)), - ] - ); - assert_eq!(sum, SourceAmount::with_base0(24)); - assert!(has_previous_page); - assert!(!has_next_page); - - // Get all uds on DESC order from particular position - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = db_reader.all_uds_of_pubkey( - &bc_db_ro, - pk, - PageInfo { - pos: Some(BlockNumber(55)), - order: false, - ..Default::default() - }, - )?; - assert_eq!( - uds, - vec![ - (BlockNumber(29), SourceAmount::with_base0(10)), - (BlockNumber(54), SourceAmount::with_base0(12)), - ] - ); - assert_eq!(sum, SourceAmount::with_base0(22)); - assert!(!has_previous_page); - assert!(has_next_page); - - Ok(()) - } - - #[test] - fn test_unspent_uds_of_pubkey() -> KvResult<()> { - let pk = PublicKey::default(); - let bc_db = duniter_dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?; - let bc_db_ro = bc_db.get_ro_handler(); - let dbs_reader = DbsReaderImpl::mem(); - - bc_db - .uds_reval_write() - .upsert(U32BE(0), SourceAmountValV2(SourceAmount::with_base0(10)))?; - bc_db - .uds_reval_write() - .upsert(U32BE(40), SourceAmountValV2(SourceAmount::with_base0(12)))?; - - bc_db.uds_write().upsert(UdIdV2(pk, BlockNumber(0)), ())?; - bc_db.uds_write().upsert(UdIdV2(pk, BlockNumber(10)), ())?; - bc_db.uds_write().upsert(UdIdV2(pk, BlockNumber(20)), ())?; - bc_db.uds_write().upsert(UdIdV2(pk, BlockNumber(30)), ())?; - bc_db.uds_write().upsert(UdIdV2(pk, BlockNumber(40)), ())?; - bc_db.uds_write().upsert(UdIdV2(pk, BlockNumber(50)), ())?; - bc_db.uds_write().upsert(UdIdV2(pk, BlockNumber(60)), ())?; - - // Get unspent uds - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = dbs_reader.unspent_uds_of_pubkey(&bc_db_ro, pk, PageInfo::default(), None, None)?; - assert_eq!(uds.len(), 7); - assert_eq!( - uds.first(), - Some(&(BlockNumber(0), SourceAmount::with_base0(10))) - ); - assert_eq!( - uds.last(), - Some(&(BlockNumber(60), SourceAmount::with_base0(12))) - ); - assert_eq!(sum, SourceAmount::with_base0(76)); - assert!(!has_previous_page); - assert!(!has_next_page); - - // Get unspent uds from particular position - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = dbs_reader.unspent_uds_of_pubkey( - &bc_db_ro, - pk, - PageInfo { - pos: Some(BlockNumber(30)), - ..Default::default() - }, - None, - None, - )?; - assert_eq!(uds.len(), 4); - assert_eq!( - uds.first(), - Some(&(BlockNumber(30), SourceAmount::with_base0(10))) - ); - assert_eq!( - uds.last(), - Some(&(BlockNumber(60), SourceAmount::with_base0(12))) - ); - assert_eq!(sum, SourceAmount::with_base0(46)); - assert!(has_previous_page); - assert!(!has_next_page); - - // Get unspent uds in order DESC - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = dbs_reader.unspent_uds_of_pubkey( - &bc_db_ro, - pk, - PageInfo { - order: false, - ..Default::default() - }, - None, - None, - )?; - assert_eq!(uds.len(), 7); - assert_eq!( - uds.first(), - Some(&(BlockNumber(0), SourceAmount::with_base0(10))) - ); - assert_eq!( - uds.last(), - Some(&(BlockNumber(60), SourceAmount::with_base0(12))) - ); - assert_eq!(sum, SourceAmount::with_base0(76)); - assert!(!has_previous_page); - assert!(!has_next_page); - - // Get unspent uds in order DESC from particular position - let PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - } = dbs_reader.unspent_uds_of_pubkey( - &bc_db_ro, - pk, - PageInfo { - pos: Some(BlockNumber(40)), - order: false, - ..Default::default() - }, - None, - None, - )?; - assert_eq!(uds.len(), 5); - assert_eq!( - uds.first(), - Some(&(BlockNumber(0), SourceAmount::with_base0(10))) - ); - assert_eq!( - uds.last(), - Some(&(BlockNumber(40), SourceAmount::with_base0(12))) - ); - assert_eq!(sum, SourceAmount::with_base0(52)); - assert!(!has_previous_page); - assert!(has_next_page); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/dbs-reader/src/utxos.rs b/rust-libs/modules/gva/dbs-reader/src/utxos.rs deleted file mode 100644 index ab19edcc6..000000000 --- a/rust-libs/modules/gva/dbs-reader/src/utxos.rs +++ /dev/null @@ -1,500 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use dubp::documents::dubp_wallet::prelude::*; -use duniter_dbs::SourceAmountValV2; - -use crate::*; - -#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] -pub struct UtxoCursor { - pub block_number: BlockNumber, - pub tx_hash: Hash, - pub output_index: u8, -} -impl std::fmt::Display for UtxoCursor { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}:{}:{}", - self.block_number, self.tx_hash, self.output_index, - ) - } -} - -impl FromStr for UtxoCursor { - type Err = WrongCursor; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - let mut s = s.split(':'); - let block_number = s - .next() - .ok_or(WrongCursor)? - .parse() - .map_err(|_| WrongCursor)?; - let tx_hash = Hash::from_hex(s.next().ok_or(WrongCursor)?).map_err(|_| WrongCursor)?; - let output_index = s - .next() - .ok_or(WrongCursor)? - .parse() - .map_err(|_| WrongCursor)?; - Ok(Self { - block_number, - tx_hash, - output_index, - }) - } -} - -#[derive(Debug, Default)] -pub struct UtxosWithSum { - pub utxos: Vec<(UtxoCursor, SourceAmount)>, - pub sum: SourceAmount, -} - -impl DbsReaderImpl { - pub(super) fn find_script_utxos_<TxsMpDb: 'static + TxsMpV2DbReadable>( - &self, - txs_mp_db_ro: &TxsMpDb, - amount_target_opt: Option<SourceAmount>, - page_info: PageInfo<UtxoCursor>, - script: &WalletScriptV10, - ) -> anyhow::Result<PagedData<UtxosWithSum>> { - let mempool_filter = |k_res: KvResult<GvaUtxoIdDbV1>| match k_res { - Ok(gva_utxo_id) => { - match txs_mp_db_ro.utxos_ids().contains_key(&UtxoIdDbV2( - gva_utxo_id.get_tx_hash(), - gva_utxo_id.get_output_index() as u32, - )) { - Ok(false) => Some(Ok(gva_utxo_id)), - Ok(true) => None, - Err(e) => Some(Err(e)), - } - } - Err(e) => Some(Err(e)), - }; - - let script_hash = Hash::compute(script.to_string().as_bytes()); - let (mut k_min, mut k_max) = GvaUtxoIdDbV1::script_interval(script_hash); - let first_cursor_opt = if page_info.not_all() { - self.0 - .gva_utxos() - .iter(k_min..k_max, |it| { - it.keys().filter_map(mempool_filter).next_res() - })? - .map(|gva_utxo_id| UtxoCursor { - block_number: BlockNumber(gva_utxo_id.get_block_number()), - tx_hash: gva_utxo_id.get_tx_hash(), - output_index: gva_utxo_id.get_output_index(), - }) - } else { - None - }; - let last_cursor_opt = if page_info.not_all() { - self.0 - .gva_utxos() - .iter_rev(k_min..k_max, |it| { - it.keys().filter_map(mempool_filter).next_res() - })? - .map(|gva_utxo_id| UtxoCursor { - block_number: BlockNumber(gva_utxo_id.get_block_number()), - tx_hash: gva_utxo_id.get_tx_hash(), - output_index: gva_utxo_id.get_output_index(), - }) - } else { - None - }; - if let Some(ref pos) = page_info.pos { - if page_info.order { - k_min = GvaUtxoIdDbV1::new_( - script_hash, - pos.block_number.0, - pos.tx_hash, - pos.output_index, - ); - } else { - k_max = GvaUtxoIdDbV1::new_( - script_hash, - pos.block_number.0, - pos.tx_hash, - pos.output_index, - ); - } - } - let UtxosWithSum { utxos, mut sum } = if page_info.order { - self.0.gva_utxos().iter(k_min..k_max, |it| { - find_script_utxos_inner(txs_mp_db_ro, amount_target_opt, page_info, it) - })? - } else { - self.0.gva_utxos().iter_rev(k_min..k_max, |it| { - find_script_utxos_inner(txs_mp_db_ro, amount_target_opt, page_info, it) - })? - }; - - if amount_target_opt.is_none() { - sum = utxos.iter().map(|(_utxo_id_with_bn, sa)| *sa).sum(); - } - - let order = page_info.order; - - Ok(PagedData { - has_next_page: has_next_page( - utxos - .iter() - .map(|(utxo_id_with_bn, _sa)| utxo_id_with_bn.into()), - last_cursor_opt, - page_info, - order, - ), - has_previous_page: has_previous_page( - utxos - .iter() - .map(|(utxo_id_with_bn, _sa)| utxo_id_with_bn.into()), - first_cursor_opt, - page_info, - order, - ), - data: UtxosWithSum { utxos, sum }, - }) - } - pub(super) fn first_scripts_utxos_( - &self, - amount_target_opt: Option<SourceAmount>, - first: usize, - scripts: &[WalletScriptV10], - ) -> anyhow::Result<Vec<ArrayVec<[Utxo; MAX_FIRST_UTXOS]>>> { - let iter = scripts.iter().map(|script| { - let (k_min, k_max) = - GvaUtxoIdDbV1::script_interval(Hash::compute(script.to_string().as_bytes())); - self.0.gva_utxos().iter(k_min..k_max, |it| { - it.take(first) - .map_ok(|(k, v)| Utxo { - amount: v.0, - tx_hash: k.get_tx_hash(), - output_index: k.get_output_index(), - }) - .collect::<KvResult<_>>() - }) - }); - if let Some(amount_target) = amount_target_opt { - let mut sum = SourceAmount::ZERO; - Ok(iter - .take_while(|utxos_res: &KvResult<ArrayVec<[Utxo; MAX_FIRST_UTXOS]>>| { - if let Ok(utxos) = utxos_res { - sum = sum + utxos.iter().map(|utxo| utxo.amount).sum(); - sum <= amount_target - } else { - true - } - }) - .collect::<KvResult<Vec<_>>>()?) - } else { - Ok(iter.collect::<KvResult<Vec<_>>>()?) - } - } -} - -fn find_script_utxos_inner<TxsMpDb, I>( - txs_mp_db_ro: &TxsMpDb, - amount_target_opt: Option<SourceAmount>, - page_info: PageInfo<UtxoCursor>, - utxos_iter: I, -) -> KvResult<UtxosWithSum> -where - TxsMpDb: TxsMpV2DbReadable, - I: Iterator<Item = KvResult<(GvaUtxoIdDbV1, SourceAmountValV2)>>, -{ - let mut sum = SourceAmount::ZERO; - - let it = utxos_iter.filter_map(|entry_res| match entry_res { - Ok((gva_utxo_id, SourceAmountValV2(utxo_amount))) => { - if utxo_amount.amount() < super::find_inputs::MIN_AMOUNT { - None - } else { - let tx_hash = gva_utxo_id.get_tx_hash(); - let output_index = gva_utxo_id.get_output_index(); - match txs_mp_db_ro - .utxos_ids() - .contains_key(&UtxoIdDbV2(tx_hash, output_index as u32)) - { - Ok(false) => Some(Ok(( - UtxoCursor { - tx_hash, - output_index, - block_number: BlockNumber(gva_utxo_id.get_block_number()), - }, - utxo_amount, - ))), - Ok(true) => None, - Err(e) => Some(Err(e)), - } - } - } - Err(e) => Some(Err(e)), - }); - let utxos = if let Some(limit) = page_info.limit_opt { - if let Some(total_target) = amount_target_opt { - it.take(limit.get()) - .take_while(|res| match res { - Ok((_, utxo_amount)) => { - if sum < total_target { - sum = sum + *utxo_amount; - true - } else { - false - } - } - Err(_) => true, - }) - .collect::<KvResult<Vec<_>>>()? - } else { - it.take(limit.get()).collect::<KvResult<Vec<_>>>()? - } - } else if let Some(total_target) = amount_target_opt { - it.take_while(|res| match res { - Ok((_, utxo_amount)) => { - if sum < total_target { - sum = sum + *utxo_amount; - true - } else { - false - } - } - Err(_) => true, - }) - .collect::<KvResult<Vec<_>>>()? - } else { - it.collect::<KvResult<Vec<_>>>()? - }; - - Ok(UtxosWithSum { utxos, sum }) -} - -#[cfg(test)] -mod tests { - - use super::*; - use dubp::crypto::keys::PublicKey as _; - use duniter_dbs::databases::txs_mp_v2::TxsMpV2DbWritable; - use duniter_gva_db::GvaV1DbWritable; - use unwrap::unwrap; - - #[test] - fn test_first_scripts_utxos() -> anyhow::Result<()> { - let script = WalletScriptV10::single_sig(PublicKey::default()); - let script2 = WalletScriptV10::single_sig(unwrap!(PublicKey::from_base58( - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - ))); - - let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?; - let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) }); - - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script.clone(), 0, Hash::default(), 0), - SourceAmountValV2(SourceAmount::with_base0(500)), - )?; - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script.clone(), 1, Hash::default(), 1), - SourceAmountValV2(SourceAmount::with_base0(800)), - )?; - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script.clone(), 2, Hash::default(), 2), - SourceAmountValV2(SourceAmount::with_base0(1_200)), - )?; - - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script2.clone(), 0, Hash::default(), 0), - SourceAmountValV2(SourceAmount::with_base0(400)), - )?; - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script2.clone(), 1, Hash::default(), 1), - SourceAmountValV2(SourceAmount::with_base0(700)), - )?; - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script2.clone(), 2, Hash::default(), 2), - SourceAmountValV2(SourceAmount::with_base0(1_100)), - )?; - - assert_eq!( - db_reader.first_scripts_utxos(None, 2, &[script, script2])?, - vec![ - [ - Utxo { - amount: SourceAmount::with_base0(500), - tx_hash: Hash::default(), - output_index: 0, - }, - Utxo { - amount: SourceAmount::with_base0(800), - tx_hash: Hash::default(), - output_index: 1, - }, - ] - .iter() - .copied() - .collect::<ArrayVec<_>>(), - [ - Utxo { - amount: SourceAmount::with_base0(400), - tx_hash: Hash::default(), - output_index: 0, - }, - Utxo { - amount: SourceAmount::with_base0(700), - tx_hash: Hash::default(), - output_index: 1, - }, - ] - .iter() - .copied() - .collect::<ArrayVec<_>>() - ] - ); - - Ok(()) - } - - #[test] - fn test_find_script_utxos() -> anyhow::Result<()> { - let script = WalletScriptV10::single_sig(PublicKey::default()); - - let gva_db = duniter_gva_db::GvaV1Db::<Mem>::open(MemConf::default())?; - let db_reader = create_dbs_reader(unsafe { std::mem::transmute(&gva_db.get_ro_handler()) }); - let txs_mp_db = - duniter_dbs::databases::txs_mp_v2::TxsMpV2Db::<Mem>::open(MemConf::default())?; - - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script.clone(), 0, Hash::default(), 0), - SourceAmountValV2(SourceAmount::with_base0(500)), - )?; - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script.clone(), 0, Hash::default(), 1), - SourceAmountValV2(SourceAmount::with_base0(800)), - )?; - gva_db.gva_utxos_write().upsert( - GvaUtxoIdDbV1::new(script.clone(), 0, Hash::default(), 2), - SourceAmountValV2(SourceAmount::with_base0(1200)), - )?; - - // Find utxos with amount target - let PagedData { - data: UtxosWithSum { utxos, sum }, - has_next_page, - has_previous_page, - } = db_reader.find_script_utxos( - &txs_mp_db, - Some(SourceAmount::with_base0(550)), - PageInfo::default(), - &script, - )?; - - assert_eq!( - utxos, - vec![ - ( - UtxoCursor { - block_number: BlockNumber(0), - tx_hash: Hash::default(), - output_index: 0, - }, - SourceAmount::with_base0(500) - ), - ( - UtxoCursor { - block_number: BlockNumber(0), - tx_hash: Hash::default(), - output_index: 1, - }, - SourceAmount::with_base0(800) - ), - ] - ); - assert_eq!(sum, SourceAmount::with_base0(1300)); - assert!(!has_next_page); - assert!(!has_previous_page); - - // Find utxos with amount target in DESC order - let PagedData { - data: UtxosWithSum { utxos, sum }, - .. - } = db_reader.find_script_utxos( - &txs_mp_db, - Some(SourceAmount::with_base0(550)), - PageInfo { - order: false, - ..Default::default() - }, - &script, - )?; - - assert_eq!( - utxos, - vec![( - UtxoCursor { - block_number: BlockNumber(0), - tx_hash: Hash::default(), - output_index: 2, - }, - SourceAmount::with_base0(1200) - ),] - ); - assert_eq!(sum, SourceAmount::with_base0(1200)); - assert!(!has_next_page); - assert!(!has_previous_page); - - // Find utxos with limit in DESC order - let PagedData { - data: UtxosWithSum { utxos, sum }, - has_previous_page, - has_next_page, - } = db_reader.find_script_utxos( - &txs_mp_db, - None, - PageInfo { - order: false, - limit_opt: NonZeroUsize::new(2), - ..Default::default() - }, - &script, - )?; - - assert_eq!( - utxos, - vec![ - ( - UtxoCursor { - block_number: BlockNumber(0), - tx_hash: Hash::default(), - output_index: 2, - }, - SourceAmount::with_base0(1200) - ), - ( - UtxoCursor { - block_number: BlockNumber(0), - tx_hash: Hash::default(), - output_index: 1, - }, - SourceAmount::with_base0(800) - ) - ] - ); - assert_eq!(sum, SourceAmount::with_base0(2000)); - assert!(!has_next_page); - assert!(has_previous_page); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/gql/Cargo.toml b/rust-libs/modules/gva/gql/Cargo.toml deleted file mode 100644 index 08d49dd16..000000000 --- a/rust-libs/modules/gva/gql/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "duniter-gva-gql" -version = "0.1.0" -authors = ["librelois <elois@duniter.org>"] -license = "AGPL-3.0" -edition = "2018" - -[dependencies] -anyhow = "1.0.33" -arrayvec = "0.5.1" -async-graphql = "2.2.0" -async-trait = "0.1.41" -dubp = { version = "0.51.0", features = ["duniter"] } -duniter-conf = { path = "../../../duniter-conf" } -duniter-dbs = { path = "../../../duniter-dbs" } -duniter-bc-reader = { path = "../../../duniter-bc-reader" } -duniter-gva-db = { path = "../db" } -duniter-gva-dbs-reader = { path = "../dbs-reader" } -duniter-global = { path = "../../../duniter-global" } -duniter-mempools = { path = "../../../duniter-mempools" } -duniter-module = { path = "../../../duniter-module" } -fast-threadpool = "0.2.3" -flume = "0.10.0" -futures = "0.3.6" -log = "0.4.11" -resiter = "0.4.0" -serde = { version = "1.0.105", features = ["derive"] } - -[dev-dependencies] -duniter-dbs = { path = "../../../duniter-dbs", features = ["mem"] } -duniter-gva-dbs-reader = { path = "../dbs-reader", features = ["mock"] } -duniter-global = { path = "../../../duniter-global", features = ["mock"] } -mockall = "0.9.1" -pretty_assertions = "0.7" -serde_json = "1.0.53" -tokio = { version = "1.2", features = ["macros", "rt-multi-thread", "time"] } -unwrap = "1.2.1" diff --git a/rust-libs/modules/gva/gql/src/entities.rs b/rust-libs/modules/gva/gql/src/entities.rs deleted file mode 100644 index c6ac1569f..000000000 --- a/rust-libs/modules/gva/gql/src/entities.rs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -pub mod block_gva; -pub mod idty_gva; -pub mod network; -pub mod tx_gva; -pub mod ud_gva; -pub mod utxos_gva; - -use crate::*; - -#[derive(Default, async_graphql::SimpleObject)] -pub(crate) struct AggregateSum { - pub(crate) aggregate: Sum, -} - -#[derive(Default, async_graphql::SimpleObject)] -pub(crate) struct AmountWithBase { - pub(crate) amount: i32, - pub(crate) base: i32, -} - -#[derive(async_graphql::SimpleObject)] -pub(crate) struct EdgeTx { - pub(crate) direction: TxDirection, -} - -pub(crate) enum RawTxOrChanges { - FinalTx(String), - Changes(Vec<String>), -} -#[async_graphql::Object] -impl RawTxOrChanges { - /// Intermediate transactions documents for compacting sources (`null` if not needed) - async fn changes(&self) -> Option<&Vec<String>> { - if let Self::Changes(changes) = self { - Some(changes) - } else { - None - } - } - /// Transaction document that carries out the requested transfer (`null` if the amount to be sent requires too many sources) - async fn tx(&self) -> Option<&str> { - if let Self::FinalTx(raw_tx) = self { - Some(raw_tx.as_str()) - } else { - None - } - } -} - -#[derive(Default, async_graphql::SimpleObject)] -pub(crate) struct Sum { - pub(crate) sum: AmountWithBase, -} - -#[derive(Clone, Copy, Eq, PartialEq, async_graphql::Enum)] -pub(crate) enum TxDirection { - /// Received - Received, - /// Sent - Sent, -} - -#[derive(async_graphql::SimpleObject)] -pub(crate) struct TxsHistoryMempool { - /// Transactions sending - pub(crate) sending: Vec<TxGva>, - /// Transactions receiving - pub(crate) receiving: Vec<TxGva>, -} - -#[derive(Clone, async_graphql::SimpleObject)] -pub(crate) struct UtxoGva { - /// Source amount - pub(crate) amount: i64, - /// Source base - pub(crate) base: i64, - /// Hash of origin transaction - pub(crate) tx_hash: String, - /// Index of output in origin transaction - pub(crate) output_index: u32, -} - -#[derive(Clone, async_graphql::SimpleObject)] -pub(crate) struct UtxoTimedGva { - /// Source amount - pub(crate) amount: i64, - /// Source base - pub(crate) base: i64, - /// Hash of origin transaction - pub(crate) tx_hash: String, - /// Index of output in origin transaction - pub(crate) output_index: u32, - /// Written block - pub(crate) written_block: u32, - /// Written time - pub(crate) written_time: u64, -} diff --git a/rust-libs/modules/gva/gql/src/entities/block_gva.rs b/rust-libs/modules/gva/gql/src/entities/block_gva.rs deleted file mode 100644 index c5be43c5d..000000000 --- a/rust-libs/modules/gva/gql/src/entities/block_gva.rs +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use super::tx_gva::TxGva; -use crate::*; -use dubp::block::DubpBlockV10; -use duniter_dbs::BlockMetaV2; - -#[derive(async_graphql::SimpleObject)] -pub(crate) struct BlockMeta { - pub version: u64, - pub number: u32, - pub hash: String, - pub signature: String, - pub inner_hash: String, - pub previous_hash: String, - pub issuer: String, - pub time: u64, - pub pow_min: u32, - pub members_count: u64, - pub issuers_count: u32, - pub issuers_frame: u64, - pub median_time: u64, - pub nonce: u64, - pub monetary_mass: u64, - pub unit_base: u32, - pub dividend: Option<u32>, -} - -impl From<BlockMetaV2> for BlockMeta { - fn from(block_db: BlockMetaV2) -> Self { - Self::from(&block_db) - } -} -impl From<&BlockMetaV2> for BlockMeta { - fn from(block_db: &BlockMetaV2) -> Self { - BlockMeta { - version: block_db.version, - number: block_db.number, - hash: block_db.hash.to_string(), - signature: block_db.signature.to_string(), - inner_hash: block_db.inner_hash.to_string(), - previous_hash: block_db.previous_hash.to_string(), - issuer: block_db.issuer.to_string(), - time: block_db.time, - pow_min: block_db.pow_min, - members_count: block_db.members_count, - issuers_count: block_db.issuers_count, - issuers_frame: block_db.issuers_frame, - median_time: block_db.median_time, - nonce: block_db.nonce, - monetary_mass: block_db.monetary_mass, - unit_base: block_db.unit_base, - dividend: block_db.dividend.map(|sa| sa.amount() as u32), - } - } -} - -#[derive(async_graphql::SimpleObject)] -pub(crate) struct Block { - // Meta - pub version: u64, - pub number: u32, - pub hash: String, - pub signature: String, - pub inner_hash: String, - pub previous_hash: Option<String>, - pub issuer: String, - pub time: u64, - pub pow_min: u32, - pub members_count: u64, - pub issuers_count: u32, - pub issuers_frame: u64, - pub median_time: u64, - pub nonce: u64, - pub monetary_mass: u64, - pub unit_base: u32, - pub dividend: Option<u32>, - // Payload - /// Identities - pub identities: Vec<String>, - /// joiners - pub joiners: Vec<String>, - /// Actives (=renewals) - pub actives: Vec<String>, - /// Leavers - pub leavers: Vec<String>, - /// Revokeds - pub revoked: Vec<String>, - /// Excludeds - pub excluded: Vec<String>, - /// Certifications - pub certifications: Vec<String>, - pub transactions: Vec<TxGva>, -} - -impl From<&DubpBlockV10> for Block { - fn from(block: &DubpBlockV10) -> Self { - let block = block.to_string_object(); - Block { - // Meta - version: block.version, - number: block.number as u32, - hash: block.hash.unwrap_or_default(), - signature: block.signature, - inner_hash: block.inner_hash.unwrap_or_default(), - previous_hash: block.previous_hash, - issuer: block.issuer, - time: block.time, - pow_min: block.pow_min as u32, - members_count: block.members_count, - issuers_count: block.issuers_count as u32, - issuers_frame: block.issuers_frame, - median_time: block.median_time, - nonce: block.nonce, - monetary_mass: block.monetary_mass, - unit_base: block.unit_base as u32, - dividend: block.dividend.map(|amount| amount as u32), - // Payload - identities: block.identities, - joiners: block.joiners, - actives: block.actives, - leavers: block.leavers, - revoked: block.revoked, - excluded: block.excluded, - certifications: block.certifications, - transactions: block.transactions.into_iter().map(Into::into).collect(), - } - } -} - -impl From<&BlockMetaV2> for Block { - fn from(block: &BlockMetaV2) -> Self { - Block { - // Meta - version: block.version, - number: block.number, - hash: block.hash.to_string(), - signature: block.signature.to_string(), - inner_hash: block.inner_hash.to_string(), - previous_hash: Some(block.previous_hash.to_string()), - issuer: block.issuer.to_string(), - time: block.time, - pow_min: block.pow_min, - members_count: block.members_count, - issuers_count: block.issuers_count, - issuers_frame: block.issuers_frame, - median_time: block.median_time, - nonce: block.nonce, - monetary_mass: block.monetary_mass, - unit_base: block.unit_base, - dividend: block.dividend.map(|sa| sa.amount() as u32), - // Payload - identities: vec![], - joiners: vec![], - actives: vec![], - leavers: vec![], - revoked: vec![], - excluded: vec![], - certifications: vec![], - transactions: vec![], - } - } -} diff --git a/rust-libs/modules/gva/gql/src/entities/idty_gva.rs b/rust-libs/modules/gva/gql/src/entities/idty_gva.rs deleted file mode 100644 index ee77b0e4d..000000000 --- a/rust-libs/modules/gva/gql/src/entities/idty_gva.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#[derive(async_graphql::SimpleObject)] -pub(crate) struct Identity { - pub is_member: bool, - pub username: String, -} diff --git a/rust-libs/modules/gva/gql/src/entities/network.rs b/rust-libs/modules/gva/gql/src/entities/network.rs deleted file mode 100644 index 7f99918c0..000000000 --- a/rust-libs/modules/gva/gql/src/entities/network.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#[derive(Default, async_graphql::SimpleObject)] -#[graphql(name = "Peer")] -pub struct PeerCardGva { - pub version: u32, - pub currency: String, - pub pubkey: String, - pub blockstamp: String, - pub endpoints: Vec<String>, - pub status: String, - pub signature: String, -} -impl From<duniter_dbs::PeerCardDbV1> for PeerCardGva { - fn from(peer: duniter_dbs::PeerCardDbV1) -> Self { - Self { - version: peer.version, - currency: peer.currency, - pubkey: peer.pubkey, - blockstamp: peer.blockstamp, - endpoints: peer.endpoints, - status: peer.status, - signature: peer.signature, - } - } -} - -#[derive(Default, async_graphql::SimpleObject)] -#[graphql(name = "Head")] -pub struct HeadGva { - pub api: String, - pub pubkey: String, - pub blockstamp: String, - pub software: String, - pub software_version: String, - pub pow_prefix: u32, - pub free_member_room: u32, - pub free_mirror_room: u32, - pub signature: String, -} -impl From<duniter_dbs::DunpHeadDbV1> for HeadGva { - fn from(head: duniter_dbs::DunpHeadDbV1) -> Self { - Self { - api: head.api, - pubkey: head.pubkey.to_string(), - blockstamp: head.blockstamp.to_string(), - software: head.software, - software_version: head.software_version, - pow_prefix: head.pow_prefix, - free_member_room: head.free_member_room, - free_mirror_room: head.free_member_room, - signature: head.signature.to_string(), - } - } -} - -#[derive(async_graphql::SimpleObject)] -pub(crate) struct PeerWithHeads { - pub peer: PeerCardGva, - pub heads: Vec<HeadGva>, -} diff --git a/rust-libs/modules/gva/gql/src/entities/tx_gva.rs b/rust-libs/modules/gva/gql/src/entities/tx_gva.rs deleted file mode 100644 index 6fd376433..000000000 --- a/rust-libs/modules/gva/gql/src/entities/tx_gva.rs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use dubp::documents::transaction::TransactionDocumentV10Stringified; -use duniter_gva_db::GvaTxDbV1; - -#[derive(async_graphql::SimpleObject)] -pub(crate) struct TxGva { - /// Version. - pub version: i32, - /// Currency. - pub currency: String, - /// Blockstamp - pub blockstamp: String, - /// Locktime - pub locktime: u64, - /// Document issuers. - pub issuers: Vec<String>, - /// Transaction inputs. - pub inputs: Vec<String>, - /// Inputs unlocks. - pub unlocks: Vec<String>, - /// Transaction outputs. - pub outputs: Vec<String>, - /// Transaction comment - pub comment: String, - /// Document signatures - pub signatures: Vec<String>, - /// Transaction hash - pub hash: String, - /// Written block - pub written_block: Option<String>, - /// Written Time - pub written_time: Option<i64>, -} - -impl From<GvaTxDbV1> for TxGva { - fn from(db_tx: GvaTxDbV1) -> Self { - let mut self_: TxGva = (&db_tx.tx).into(); - self_.written_block = Some(db_tx.written_block.to_string()); - self_.written_time = Some(db_tx.written_time); - self_ - } -} - -impl From<&TransactionDocumentV10> for TxGva { - fn from(tx: &TransactionDocumentV10) -> Self { - let tx_stringified = tx.to_string_object(); - Self::from(tx_stringified) - } -} - -impl From<TransactionDocumentV10Stringified> for TxGva { - fn from(tx_stringified: TransactionDocumentV10Stringified) -> Self { - Self { - version: 10, - currency: tx_stringified.currency, - blockstamp: tx_stringified.blockstamp, - locktime: tx_stringified.locktime, - issuers: tx_stringified.issuers, - inputs: tx_stringified.inputs, - unlocks: tx_stringified.unlocks, - outputs: tx_stringified.outputs, - comment: tx_stringified.comment, - signatures: tx_stringified.signatures, - hash: tx_stringified.hash.unwrap_or_default(), - written_block: None, - written_time: None, - } - } -} diff --git a/rust-libs/modules/gva/gql/src/entities/ud_gva.rs b/rust-libs/modules/gva/gql/src/entities/ud_gva.rs deleted file mode 100644 index e268f5b67..000000000 --- a/rust-libs/modules/gva/gql/src/entities/ud_gva.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, async_graphql::SimpleObject)] -pub(crate) struct CurrentUdGva { - /// Ud amount - pub(crate) amount: i64, - /// Ud base - pub(crate) base: i64, -} - -#[derive(Clone, async_graphql::SimpleObject)] -pub(crate) struct RevalUdGva { - /// Ud amount - pub(crate) amount: i64, - /// Ud base - pub(crate) base: i64, - /// Number of the block that revaluate ud amount - pub(crate) block_number: u32, -} - -#[derive(Clone, async_graphql::SimpleObject)] -pub(crate) struct UdGva { - /// Ud amount - pub(crate) amount: i64, - /// Ud base - pub(crate) base: i64, - /// Issuer of this universal dividend - pub(crate) issuer: PubKeyGva, - /// Number of the block that created this UD - pub(crate) block_number: u32, - /// Blockchain time of the block that created this UD - pub(crate) blockchain_time: u64, -} diff --git a/rust-libs/modules/gva/gql/src/entities/utxos_gva.rs b/rust-libs/modules/gva/gql/src/entities/utxos_gva.rs deleted file mode 100644 index 9bd3e7990..000000000 --- a/rust-libs/modules/gva/gql/src/entities/utxos_gva.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub(crate) struct UtxosGva(pub arrayvec::ArrayVec<[UtxoGva; 40]>); -impl async_graphql::Type for UtxosGva { - fn type_name() -> Cow<'static, str> { - Cow::Owned(format!("[{}]", UtxoGva::qualified_type_name())) - } - - fn qualified_type_name() -> String { - format!("[{}]!", UtxoGva::qualified_type_name()) - } - - fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String { - UtxoGva::create_type_info(registry); - Self::qualified_type_name() - } -} -#[async_trait::async_trait] -impl async_graphql::OutputType for UtxosGva { - async fn resolve( - &self, - ctx: &async_graphql::ContextSelectionSet<'_>, - field: &async_graphql::Positioned<async_graphql::parser::types::Field>, - ) -> async_graphql::ServerResult<async_graphql::Value> { - async_graphql::resolver_utils::resolve_list(ctx, field, &self.0, Some(self.0.len())).await - } -} diff --git a/rust-libs/modules/gva/gql/src/inputs.rs b/rust-libs/modules/gva/gql/src/inputs.rs deleted file mode 100644 index b90469094..000000000 --- a/rust-libs/modules/gva/gql/src/inputs.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(async_graphql::InputObject, Clone, Copy, Default)] -pub(crate) struct TimeInterval { - pub(crate) from: Option<u64>, - pub(crate) to: Option<u64>, -} - -#[derive(async_graphql::InputObject)] -pub(crate) struct TxIssuer { - /// Account script (default is a script needed all provided signers) - pub(crate) script: Option<String>, - /// Signers - #[graphql(validator(ListMinLength(length = "1")))] - pub(crate) signers: Vec<String>, - /// XHX codes needed to unlock funds - #[graphql(validator(ListMinLength(length = "1")))] - pub(crate) codes: Option<Vec<String>>, - /// Amount - #[graphql(validator(IntGreaterThan(value = "0")))] - pub(crate) amount: i32, -} - -#[derive(async_graphql::InputObject)] -pub(crate) struct TxRecipient { - /// Amount - #[graphql(validator(IntGreaterThan(value = "0")))] - pub(crate) amount: i32, - /// Account script - pub(crate) script: String, -} - -#[derive(Clone, Copy, async_graphql::Enum, Eq, PartialEq)] -pub(crate) enum UdsFilter { - All, - Unspent, -} -impl Default for UdsFilter { - fn default() -> Self { - UdsFilter::All - } -} diff --git a/rust-libs/modules/gva/gql/src/inputs_validators.rs b/rust-libs/modules/gva/gql/src/inputs_validators.rs deleted file mode 100644 index b2578c22b..000000000 --- a/rust-libs/modules/gva/gql/src/inputs_validators.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub(crate) struct TxCommentValidator; - -impl async_graphql::validators::InputValueValidator for TxCommentValidator { - fn is_valid(&self, value: &async_graphql::Value) -> Result<(), String> { - if let async_graphql::Value::String(comment) = value { - if !TransactionDocumentV10::verify_comment(&comment) { - // Validation failed - Err("invalid comment".to_owned()) - } else { - // Validation succeeded - Ok(()) - } - } else { - // If the type does not match we can return None and built-in validations - // will pick up on the error - Ok(()) - } - } -} diff --git a/rust-libs/modules/gva/gql/src/lib.rs b/rust-libs/modules/gva/gql/src/lib.rs deleted file mode 100644 index 019f8ce9a..000000000 --- a/rust-libs/modules/gva/gql/src/lib.rs +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -mod entities; -mod inputs; -mod inputs_validators; -mod mutations; -mod pagination; -mod queries; -mod scalars; -mod schema; -mod subscriptions; - -pub use schema::{build_schema_with_data, get_schema_definition, GvaSchema, GvaSchemaData}; - -use crate::entities::{ - block_gva::{Block, BlockMeta}, - idty_gva::Identity, - network::{HeadGva, PeerCardGva, PeerWithHeads}, - tx_gva::TxGva, - ud_gva::{CurrentUdGva, RevalUdGva, UdGva}, - utxos_gva::UtxosGva, - AggregateSum, AmountWithBase, EdgeTx, RawTxOrChanges, Sum, TxDirection, TxsHistoryMempool, - UtxoGva, UtxoTimedGva, -}; -use crate::inputs::{TxIssuer, TxRecipient, UdsFilter}; -use crate::inputs_validators::TxCommentValidator; -use crate::pagination::Pagination; -use crate::scalars::{PkOrScriptGva, PubKeyGva}; -#[cfg(test)] -use crate::tests::AsyncAccessor; -#[cfg(test)] -use crate::tests::DbsReaderImpl; -use async_graphql::connection::{Connection, Edge, EmptyFields}; -use async_graphql::validators::{IntGreaterThan, IntRange, ListMaxLength, ListMinLength}; -use dubp::common::crypto::keys::{ed25519::PublicKey, PublicKey as _}; -use dubp::common::prelude::*; -use dubp::crypto::hashs::Hash; -use dubp::documents::prelude::*; -use dubp::documents::transaction::{TransactionDocumentTrait, TransactionDocumentV10}; -use dubp::documents_parser::prelude::*; -use dubp::wallet::prelude::*; -use duniter_dbs::databases::txs_mp_v2::TxsMpV2DbReadable; -use duniter_dbs::prelude::*; -use duniter_dbs::{kv_typed::prelude::*, FileBackend}; -#[cfg(not(test))] -use duniter_global::AsyncAccessor; -use duniter_gva_dbs_reader::pagination::PageInfo; -use duniter_gva_dbs_reader::DbsReader; -#[cfg(not(test))] -use duniter_gva_dbs_reader::DbsReaderImpl; -use duniter_mempools::TxsMempool; -use futures::{Stream, StreamExt}; -use resiter::map::Map; -use std::{borrow::Cow, convert::TryFrom, num::NonZeroUsize, ops::Deref}; - -#[derive(Clone, Copy, Debug, Default)] -pub struct QueryContext { - pub is_whitelisted: bool, -} - -#[derive(Debug, Default)] -pub struct ServerMetaData { - pub currency: String, - pub self_pubkey: PublicKey, - pub software_version: &'static str, -} - -#[cfg(test)] -mod tests { - pub use duniter_global::{CurrentMeta, MockAsyncAccessor}; - pub use duniter_gva_dbs_reader::MockDbsReader; - - use super::*; - use fast_threadpool::ThreadPoolConfig; - - pub type AsyncAccessor = duniter_dbs::kv_typed::prelude::Arc<MockAsyncAccessor>; - pub type DbsReaderImpl = duniter_dbs::kv_typed::prelude::Arc<MockDbsReader>; - - pub(crate) fn create_schema( - mock_cm: MockAsyncAccessor, - dbs_ops: MockDbsReader, - ) -> KvResult<GvaSchema> { - let dbs = SharedDbs::mem()?; - let threadpool = fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs); - Ok(schema::build_schema_with_data( - schema::GvaSchemaData { - cm_accessor: Arc::new(mock_cm), - dbs_pool: threadpool.into_async_handler(), - dbs_reader: Arc::new(dbs_ops), - server_meta_data: ServerMetaData { - currency: "test_currency".to_owned(), - self_pubkey: PublicKey::default(), - software_version: "test", - }, - txs_mempool: TxsMempool::new(10), - }, - true, - )) - } - - pub(crate) async fn exec_graphql_request( - schema: &GvaSchema, - request: &str, - ) -> anyhow::Result<serde_json::Value> { - Ok(serde_json::to_value( - schema - .execute(async_graphql::Request::new(request).data(QueryContext::default())) - .await, - )?) - } - - /*pub(crate) fn create_schema_sub(dbs: SharedDbs<FileBackend>) -> KvResult<GvaSchema> { - let threadpool = fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs); - Ok(schema::build_schema_with_data( - schema::GvaSchemaData { - dbs_pool: threadpool.into_async_handler(), - dbs_reader: Arc::new(MockDbsReader::new()), - server_meta_data: ServerMetaData { - currency: "test_currency".to_owned(), - self_pubkey: PublicKey::default(), - software_version: "test", - }, - txs_mempool: TxsMempool::new(10), - }, - true, - )) - } - - pub(crate) fn exec_graphql_subscription( - schema: &GvaSchema, - request: String, - ) -> impl Stream<Item = serde_json::Result<serde_json::Value>> + Send { - schema.execute_stream(request).map(serde_json::to_value) - }*/ -} diff --git a/rust-libs/modules/gva/gql/src/mutations.rs b/rust-libs/modules/gva/gql/src/mutations.rs deleted file mode 100644 index 3d258e9ae..000000000 --- a/rust-libs/modules/gva/gql/src/mutations.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Clone, Copy, Default)] -pub struct MutationRoot; - -#[async_graphql::Object] -impl MutationRoot { - /// Process a transaction - /// Return the transaction if it successfully inserted - async fn tx( - &self, - ctx: &async_graphql::Context<'_>, - raw_tx: String, - ) -> async_graphql::Result<TxGva> { - let tx = TransactionDocumentV10::parse_from_raw_text(&raw_tx)?; - - let data = ctx.data::<GvaSchemaData>()?; - let expected_currency = data.server_meta_data.currency.clone(); - - tx.verify(Some(&expected_currency))?; - - let server_pubkey = data.server_meta_data.self_pubkey; - let txs_mempool = data.txs_mempool; - - let tx = data - .dbs_pool - .execute(move |dbs| { - txs_mempool - .add_pending_tx(&dbs.bc_db_ro, server_pubkey, &dbs.txs_mp_db, &tx) - .map(|()| tx) - }) - .await??; - - Ok(TxGva::from(&tx)) - } - - /// Process several transactions - /// Return an array of successfully inserted transactions - async fn txs( - &self, - ctx: &async_graphql::Context<'_>, - raw_txs: Vec<String>, - ) -> async_graphql::Result<Vec<TxGva>> { - let txs = raw_txs - .iter() - .map(|raw_tx| TransactionDocumentV10::parse_from_raw_text(&raw_tx)) - .collect::<Result<Vec<TransactionDocumentV10>, _>>()?; - - let data = ctx.data::<GvaSchemaData>()?; - let expected_currency = data.server_meta_data.currency.clone(); - - let server_pubkey = data.server_meta_data.self_pubkey; - let txs_mempool = data.txs_mempool; - - let mut processed_txs = Vec::with_capacity(txs.len()); - for tx in txs { - tx.verify(Some(&expected_currency))?; - let tx = data - .dbs_pool - .execute(move |dbs| { - txs_mempool - .add_pending_tx(&dbs.bc_db_ro, server_pubkey, &dbs.txs_mp_db, &tx) - .map(|()| tx) - }) - .await??; - processed_txs.push(TxGva::from(&tx)); - } - - Ok(processed_txs) - } -} diff --git a/rust-libs/modules/gva/gql/src/pagination.rs b/rust-libs/modules/gva/gql/src/pagination.rs deleted file mode 100644 index 98db4e9ab..000000000 --- a/rust-libs/modules/gva/gql/src/pagination.rs +++ /dev/null @@ -1,73 +0,0 @@ -use std::str::FromStr; - -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -const MAX_PAGE_SIZE: u32 = 1_000; - -#[derive(Clone, Copy, async_graphql::Enum, Eq, PartialEq)] -pub(crate) enum Order { - /// Ascending order - Asc, - /// Decreasing order - Desc, -} -impl Default for Order { - fn default() -> Self { - Order::Asc - } -} - -#[derive(async_graphql::InputObject)] -pub(crate) struct Pagination { - /// Identifier of the 1st desired element (of the last one in descending order) - cursor: Option<String>, - ord: Order, - page_size: u32, -} - -impl Default for Pagination { - fn default() -> Self { - Pagination { - cursor: None, - ord: Order::default(), - page_size: 10, - } - } -} - -impl Pagination { - pub(crate) fn convert_to_page_info< - E: 'static + std::error::Error + Send + Sync, - T: FromStr<Err = E>, - >( - self, - is_whitelisted: bool, - ) -> anyhow::Result<duniter_gva_dbs_reader::PageInfo<T>> { - let page_size = if is_whitelisted || (self.page_size > 0 && self.page_size < MAX_PAGE_SIZE) - { - NonZeroUsize::new(self.page_size as usize) - } else { - return Err(anyhow::Error::msg("pageSize must be between 1 and 1000.")); - }; - Ok(duniter_gva_dbs_reader::PageInfo::new( - self.cursor.map(|c| T::from_str(&c)).transpose()?, - self.ord == Order::Asc, - page_size, - )) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries.rs b/rust-libs/modules/gva/gql/src/queries.rs deleted file mode 100644 index 7357f4937..000000000 --- a/rust-libs/modules/gva/gql/src/queries.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -pub mod account_balance; -pub mod block; -pub mod current_block; -pub mod current_frame; -pub mod first_utxos_of_scripts; -pub mod gen_tx; -pub mod idty; -pub mod network; -pub mod txs_history; -pub mod uds; -pub mod utxos_of_script; - -use crate::*; - -#[derive(async_graphql::MergedObject, Default)] -pub struct QueryRoot( - queries::NodeQuery, - queries::account_balance::AccountBalanceQuery, - queries::block::BlockQuery, - queries::current_block::CurrentBlockQuery, - queries::current_frame::CurrentFrameQuery, - queries::first_utxos_of_scripts::FirstUtxosQuery, - queries::gen_tx::GenTxsQuery, - queries::idty::IdtyQuery, - queries::network::NetworkQuery, - queries::txs_history::TxsHistoryBlockchainQuery, - queries::txs_history::TxsHistoryMempoolQuery, - queries::uds::UdsQuery, - queries::utxos_of_script::UtxosQuery, -); - -#[derive(Default, async_graphql::SimpleObject)] -struct NodeQuery { - node: Node, -} - -#[derive(Default)] -struct Node; - -#[async_graphql::Object] -impl Node { - /// Peer card - async fn peer( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<Option<PeerCardGva>> { - let data = ctx.data::<GvaSchemaData>()?; - - if let Some(self_peer_old) = data - .cm_accessor() - .get_self_peer_old(|self_peer_old| self_peer_old.clone()) - .await - { - Ok(Some(PeerCardGva::from(self_peer_old))) - } else { - Ok(None) - } - } - /// Software - async fn software(&self) -> &'static str { - duniter_module::SOFTWARE_NAME - } - /// Software version - async fn version( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<&'static str> { - let data = ctx.data::<GvaSchemaData>()?; - Ok(data.server_meta_data.software_version) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/account_balance.rs b/rust-libs/modules/gva/gql/src/queries/account_balance.rs deleted file mode 100644 index 9f25cdeca..000000000 --- a/rust-libs/modules/gva/gql/src/queries/account_balance.rs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Default)] -pub(crate) struct AccountBalanceQuery; -#[async_graphql::Object] -impl AccountBalanceQuery { - /// Get the balance of an account identified by a public key or a script. - /// - /// If the balance is null, the account has never been used. If the balance is zero, the account has already transited money in the past. - async fn balance( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "Account script or public key")] script: PkOrScriptGva, - ) -> async_graphql::Result<Option<AmountWithBase>> { - let data = ctx.data::<GvaSchemaData>()?; - let dbs_reader = data.dbs_reader(); - - Ok(data - .dbs_pool - .execute(move |_| dbs_reader.get_account_balance(&script.0)) - .await?? - .map(|balance| AmountWithBase { - amount: balance.0.amount() as i32, - base: balance.0.base() as i32, - })) - } - /// Get the balance of several accounts in a single request - /// - /// Each account can be identified by a public key or a script. It is possible to mix the two in the same request. - /// The balances are returned in the order of the accounts provided as input. Each account has a balance, - /// which is null if the account does not exist. - async fn balances( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "Accounts scripts or publics keys")] scripts: Vec<PkOrScriptGva>, - ) -> async_graphql::Result<Vec<Option<AmountWithBase>>> { - let data = ctx.data::<GvaSchemaData>()?; - let dbs_reader = data.dbs_reader(); - - Ok(data - .dbs_pool - .execute(move |_| { - scripts - .iter() - .map(|account_script| { - dbs_reader - .get_account_balance(&account_script.0) - .map(|balance_opt| { - balance_opt.map(|balance| AmountWithBase { - amount: balance.0.amount() as i32, - base: balance.0.base() as i32, - }) - }) - }) - .collect::<Result<Vec<_>, _>>() - }) - .await??) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::*; - use duniter_dbs::SourceAmountValV2; - - #[tokio::test] - async fn query_balance() -> anyhow::Result<()> { - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_get_account_balance() - .withf(|s| { - s == &WalletScriptV10::single_sig( - PublicKey::from_base58("DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP") - .expect("wrong pubkey"), - ) - }) - .times(1) - .returning(|_| Ok(Some(SourceAmountValV2(SourceAmount::with_base0(38))))); - let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?; - assert_eq!( - exec_graphql_request( - &schema, - r#"{ balance(script: "DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP") {amount} }"# - ) - .await?, - serde_json::json!({ - "data": { - "balance": { - "amount": 38 - } - } - }) - ); - Ok(()) - } - - #[tokio::test] - async fn query_balances() -> anyhow::Result<()> { - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_get_account_balance() - .withf(|s| { - s == &WalletScriptV10::single_sig( - PublicKey::from_base58("DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP") - .expect("wrong pubkey"), - ) - }) - .times(1) - .returning(|_| Ok(Some(SourceAmountValV2(SourceAmount::with_base0(38))))); - let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?; - assert_eq!( - exec_graphql_request( - &schema, - r#"{ balances(scripts: ["DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP"]) {amount} }"# - ) - .await?, - serde_json::json!({ - "data": { - "balances": [{ - "amount": 38 - }] - } - }) - ); - Ok(()) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/block.rs b/rust-libs/modules/gva/gql/src/queries/block.rs deleted file mode 100644 index 1d09cb664..000000000 --- a/rust-libs/modules/gva/gql/src/queries/block.rs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (C) 2021 Pascal Engélibert -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use duniter_gva_dbs_reader::PagedData; - -#[derive(Default)] -pub(crate) struct BlockQuery; -#[async_graphql::Object] -impl BlockQuery { - /// Get block by number - async fn block_by_number( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "block number")] number: u32, - ) -> async_graphql::Result<Option<BlockMeta>> { - let data = ctx.data::<GvaSchemaData>()?; - let dbs_reader = data.dbs_reader(); - - let block = data - .dbs_pool - .execute(move |dbs| dbs_reader.block(&dbs.bc_db_ro, U32BE(number))) - .await??; - - Ok(block.map(|block| BlockMeta::from(&block))) - } - - /// Get blocks - async fn blocks( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "pagination", default)] pagination: Pagination, - ) -> async_graphql::Result<Connection<String, BlockMeta, EmptyFields, EmptyFields>> { - let QueryContext { is_whitelisted } = ctx.data::<QueryContext>()?; - let page_info = Pagination::convert_to_page_info(pagination, *is_whitelisted)?; - - let data = ctx.data::<GvaSchemaData>()?; - let dbs_reader = data.dbs_reader(); - - let PagedData { - data: blocks, - has_next_page, - has_previous_page, - } = data - .dbs_pool - .execute(move |dbs| dbs_reader.blocks(&dbs.bc_db_ro, page_info)) - .await??; - - let mut conn = Connection::new(has_previous_page, has_next_page); - - conn.append(blocks.into_iter().map(|(block_cursor, block)| { - Edge::new(block_cursor.to_string(), BlockMeta::from(block)) - })); - - Ok(conn) - } -} - -#[cfg(test)] -mod tests { - use super::BlockNumber; - use crate::tests::*; - use duniter_dbs::BlockMetaV2; - use duniter_gva_dbs_reader::{block::BlockCursor, PagedData}; - - #[tokio::test] - async fn test_block_by_number() -> anyhow::Result<()> { - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_block() - .withf(|_, s| s.0 == 0) - .times(1) - .returning(|_, _| Ok(Some(BlockMetaV2::default()))); - let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?; - assert_eq!( - exec_graphql_request(&schema, r#"{ blockByNumber(number: 0) {number} }"#).await?, - serde_json::json!({ - "data": { - "blockByNumber": { - "number": BlockMetaV2::default().number, - } - } - }) - ); - Ok(()) - } - - #[tokio::test] - async fn test_blocks() -> anyhow::Result<()> { - let mut dbs_reader = MockDbsReader::new(); - dbs_reader.expect_blocks().times(1).returning(|_, _| { - Ok(PagedData { - data: vec![( - BlockCursor { - number: BlockNumber(0), - }, - BlockMetaV2::default(), - )], - has_next_page: false, - has_previous_page: false, - }) - }); - let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?; - assert_eq!( - exec_graphql_request( - &schema, - r#"{ blocks{pageInfo{startCursor,endCursor},edges{node{number}}} }"# - ) - .await?, - serde_json::json!({ - "data": { - "blocks": { - "edges": [ - { - "node": { - "number": BlockMetaV2::default().number, - } - } - ], - "pageInfo": { - "endCursor": BlockMetaV2::default().number.to_string(), - "startCursor": BlockMetaV2::default().number.to_string(), - } - } - } - }) - ); - Ok(()) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/current_block.rs b/rust-libs/modules/gva/gql/src/queries/current_block.rs deleted file mode 100644 index 100706dbd..000000000 --- a/rust-libs/modules/gva/gql/src/queries/current_block.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Default)] -pub(crate) struct CurrentBlockQuery; -#[async_graphql::Object] -impl CurrentBlockQuery { - /// Get current block - async fn current_block( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<BlockMeta> { - let data = ctx.data::<GvaSchemaData>()?; - - if let Some(current_block_meta) = data - .cm_accessor() - .get_current_meta(|cm| cm.current_block_meta) - .await - { - Ok(current_block_meta.into()) - } else { - Err(async_graphql::Error::new("no blockchain")) - } - } -} - -#[cfg(test)] -mod tests { - use crate::tests::*; - - #[tokio::test] - async fn query_current_block() -> anyhow::Result<()> { - let mut mock_cm = MockAsyncAccessor::new(); - mock_cm - .expect_get_current_meta::<duniter_dbs::BlockMetaV2>() - .times(1) - .returning(|f| Some(f(&CurrentMeta::default()))); - let schema = create_schema(mock_cm, MockDbsReader::new())?; - assert_eq!( - exec_graphql_request(&schema, r#"{ currentBlock {nonce} }"#).await?, - serde_json::json!({ - "data": { - "currentBlock": { - "nonce": 0 - } - } - }) - ); - Ok(()) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/current_frame.rs b/rust-libs/modules/gva/gql/src/queries/current_frame.rs deleted file mode 100644 index a5ba2584a..000000000 --- a/rust-libs/modules/gva/gql/src/queries/current_frame.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Default)] -pub(crate) struct CurrentFrameQuery; -#[async_graphql::Object] -impl CurrentFrameQuery { - /// Get blocks in current frame - async fn current_frame( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<Vec<BlockMeta>> { - let data = ctx.data::<GvaSchemaData>()?; - let dbs_reader = data.dbs_reader(); - - if let Some(current_block_meta) = data - .cm_accessor() - .get_current_meta(|cm| cm.current_block_meta) - .await - { - Ok(data - .dbs_pool - .execute(move |dbs| { - dbs_reader.get_current_frame(&dbs.bc_db_ro, ¤t_block_meta) - }) - .await?? - .into_iter() - .map(Into::into) - .collect()) - } else { - Ok(vec![]) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::*; - use duniter_dbs::databases::bc_v2::BcV2DbRo; - use duniter_dbs::BlockMetaV2; - - #[tokio::test] - async fn query_current_frame() -> anyhow::Result<()> { - let mut mock_cm = MockAsyncAccessor::new(); - mock_cm - .expect_get_current_meta::<BlockMetaV2>() - .times(1) - .returning(|f| { - Some(f(&CurrentMeta { - current_block_meta: BlockMetaV2 { - issuers_frame: 1, - ..Default::default() - }, - ..Default::default() - })) - }); - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_get_current_frame::<BcV2DbRo<FileBackend>>() - .times(1) - .returning(|_, _| { - Ok(vec![BlockMetaV2 { - ..Default::default() - }]) - }); - let schema = create_schema(mock_cm, dbs_reader)?; - assert_eq!( - exec_graphql_request(&schema, r#"{ currentFrame {nonce} }"#).await?, - serde_json::json!({ - "data": { - "currentFrame": [{ - "nonce": 0 - }] - } - }) - ); - Ok(()) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/first_utxos_of_scripts.rs b/rust-libs/modules/gva/gql/src/queries/first_utxos_of_scripts.rs deleted file mode 100644 index a8d3c1bd2..000000000 --- a/rust-libs/modules/gva/gql/src/queries/first_utxos_of_scripts.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Default)] -pub(crate) struct FirstUtxosQuery; -#[async_graphql::Object] -impl FirstUtxosQuery { - /// First utxos of scripts - async fn first_utxos_of_scripts( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql( - desc = "DUBP wallets scripts", - validator(ListMaxLength(length = "100")) - )] - scripts: Vec<PkOrScriptGva>, - #[graphql( - desc = "Number of first utxos to get ", - default = 10, - validator(IntRange(min = "1", max = "40")) - )] - first: i32, - ) -> async_graphql::Result<Vec<UtxosGva>> { - let scripts: Vec<WalletScriptV10> = scripts.into_iter().map(|script| script.0).collect(); - - let data = ctx.data::<GvaSchemaData>()?; - let db_reader = data.dbs_reader(); - - let utxos_matrice: Vec<arrayvec::ArrayVec<_>> = data - .dbs_pool - .execute(move |_| db_reader.first_scripts_utxos(None, first as usize, &scripts)) - .await??; - - Ok(utxos_matrice - .into_iter() - .map(|utxos| { - UtxosGva( - utxos - .into_iter() - .map(|utxo| UtxoGva { - amount: utxo.amount.amount(), - base: utxo.amount.base(), - tx_hash: utxo.tx_hash.to_hex(), - output_index: utxo.output_index as u32, - }) - .collect(), - ) - }) - .collect()) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/gen_tx.rs b/rust-libs/modules/gva/gql/src/queries/gen_tx.rs deleted file mode 100644 index 8762966a8..000000000 --- a/rust-libs/modules/gva/gql/src/queries/gen_tx.rs +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use dubp::{ - crypto::bases::BaseConversionError, - documents::transaction::v10_gen::{TransactionDocV10ComplexGen, TxV10ComplexIssuer}, - documents::transaction::UnsignedTransactionDocumentTrait, -}; -use duniter_dbs::smallvec::SmallVec; - -struct TxIssuerTyped { - script: WalletScriptV10, - signers: SmallVec<[PublicKey; 1]>, - codes: SmallVec<[String; 1]>, - amount: i32, -} -impl TryFrom<TxIssuer> for TxIssuerTyped { - type Error = async_graphql::Error; - - fn try_from(input: TxIssuer) -> async_graphql::Result<Self> { - let codes = if let Some(codes) = input.codes { - codes.into_iter().collect() - } else { - SmallVec::new() - }; - let signers: SmallVec<[PublicKey; 1]> = input - .signers - .iter() - .map(|s| PublicKey::from_base58(s)) - .collect::<Result<_, BaseConversionError>>()?; - let script = if let Some(ref script_str) = input.script { - dubp::documents_parser::wallet_script_from_str(script_str)? - } else if signers.len() <= 3 && codes.is_empty() { - match signers.len() { - 1 => WalletScriptV10::single(WalletConditionV10::Sig(signers[0])), - 2 => WalletScriptV10::and( - WalletConditionV10::Sig(signers[0]), - WalletConditionV10::Sig(signers[1]), - ), - 3 => WalletScriptV10::and_and( - WalletConditionV10::Sig(signers[0]), - WalletConditionV10::Sig(signers[1]), - WalletConditionV10::Sig(signers[2]), - ), - _ => unreachable!(), - } - } else { - return Err(async_graphql::Error::new("missing a issuer script")); - }; - Ok(Self { - script, - signers, - codes, - amount: input.amount, - }) - } -} -struct TxRecipientTyped { - amount: i32, - script: WalletScriptV10, -} -impl TryFrom<TxRecipient> for TxRecipientTyped { - type Error = async_graphql::Error; - - fn try_from(input: TxRecipient) -> async_graphql::Result<Self> { - let script = dubp::documents_parser::wallet_script_from_str(&input.script)?; - Ok(Self { - amount: input.amount, - script, - }) - } -} - -#[derive(Default)] -pub(crate) struct GenTxsQuery; -#[async_graphql::Object] -impl GenTxsQuery { - #[allow(clippy::too_many_arguments)] - /// Generate simple transaction document - async fn gen_tx( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "Transaction amount", validator(IntGreaterThan(value = "0")))] amount: i32, - #[graphql( - desc = "Cash back address, equal to issuer address by default (Ed25519 public key on base 58 representation)" - )] - cash_back_address: Option<PubKeyGva>, - #[graphql(desc = "Transaction comment", validator(TxCommentValidator))] comment: Option< - String, - >, - issuer: PubKeyGva, - #[graphql(desc = "Recipient address")] recipient: PkOrScriptGva, - #[graphql(desc = "Use mempool sources", default = false)] use_mempool_sources: bool, - ) -> async_graphql::Result<Vec<String>> { - let comment = comment.unwrap_or_default(); - let issuer = issuer.0; - let recipient = recipient.0; - - let data = ctx.data::<GvaSchemaData>()?; - let db_reader = data.dbs_reader(); - let currency = data.server_meta_data.currency.clone(); - - if let Some(current_block_meta) = data - .cm_accessor - .get_current_meta(|cm| cm.current_block_meta) - .await - { - let (inputs, inputs_sum) = data - .dbs_pool - .execute(move |dbs| { - db_reader.find_inputs( - &dbs.bc_db_ro, - &dbs.txs_mp_db, - SourceAmount::new(amount as i64, current_block_meta.unit_base as i64), - &WalletScriptV10::single(WalletConditionV10::Sig(issuer)), - use_mempool_sources, - ) - }) - .await??; - - let amount = SourceAmount::new(amount as i64, current_block_meta.unit_base as i64); - - if inputs_sum < amount { - return Err(async_graphql::Error::new("insufficient balance")); - } - - let current_blockstamp = Blockstamp { - number: BlockNumber(current_block_meta.number), - hash: BlockHash(current_block_meta.hash), - }; - - Ok(TransactionDocumentV10::generate_simple_txs( - current_blockstamp, - currency, - (inputs, inputs_sum), - issuer, - recipient, - (amount, comment), - cash_back_address.map(|pubkey_gva| pubkey_gva.0), - ) - .into_iter() - .map(|tx| tx.as_text().to_owned()) - .collect()) - } else { - Err(async_graphql::Error::new("no blockchain")) - } - } - /// Generate complex transaction document - async fn gen_complex_tx( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "Transaction issuers")] issuers: Vec<TxIssuer>, - #[graphql(desc = "Transaction recipients")] recipients: Vec<TxRecipient>, - #[graphql(desc = "Transaction comment", validator(TxCommentValidator))] comment: Option< - String, - >, - #[graphql(desc = "Use mempool sources", default = false)] use_mempool_sources: bool, - ) -> async_graphql::Result<RawTxOrChanges> { - let comment = comment.unwrap_or_default(); - let issuers = issuers - .into_iter() - .map(TryFrom::try_from) - .collect::<async_graphql::Result<Vec<TxIssuerTyped>>>()?; - let recipients = recipients - .into_iter() - .map(TryFrom::try_from) - .collect::<async_graphql::Result<Vec<TxRecipientTyped>>>()?; - - let issuers_sum: i32 = issuers.iter().map(|issuer| issuer.amount).sum(); - let recipients_sum: i32 = recipients.iter().map(|recipient| recipient.amount).sum(); - if issuers_sum != recipients_sum { - return Err(async_graphql::Error::new( - "The sum of the amounts of the issuers must be equal to the sum of the amounts of the recipients.", - )); - } - - let data = ctx.data::<GvaSchemaData>()?; - let db_reader = data.dbs_reader(); - let currency = data.server_meta_data.currency.clone(); - - if let Some(current_block_meta) = data - .cm_accessor - .get_current_meta(|cm| cm.current_block_meta) - .await - { - let issuers_inputs_with_sum = data - .dbs_pool - .execute(move |dbs| { - let mut issuers_inputs_with_sum = Vec::new(); - for issuer in issuers { - issuers_inputs_with_sum.push(( - db_reader.find_inputs( - &dbs.bc_db_ro, - &dbs.txs_mp_db, - SourceAmount::new( - issuer.amount as i64, - current_block_meta.unit_base as i64, - ), - &issuer.script, - use_mempool_sources, - )?, - issuer, - )); - } - Ok::<_, anyhow::Error>(issuers_inputs_with_sum) - }) - .await??; - - for ((_inputs, inputs_sum), issuer) in &issuers_inputs_with_sum { - let amount = - SourceAmount::new(issuer.amount as i64, current_block_meta.unit_base as i64); - if *inputs_sum < amount { - return Err(async_graphql::Error::new(format!( - "Insufficient balance for issuer {}", - issuer.script.to_string() - ))); - } - } - - let current_blockstamp = Blockstamp { - number: BlockNumber(current_block_meta.number), - hash: BlockHash(current_block_meta.hash), - }; - let base = current_block_meta.unit_base as i64; - - let (final_tx_opt, changes_txs) = TransactionDocV10ComplexGen { - blockstamp: current_blockstamp, - currency, - issuers: issuers_inputs_with_sum - .into_iter() - .map(|((inputs, inputs_sum), issuer)| TxV10ComplexIssuer { - amount: SourceAmount::new(issuer.amount as i64, base), - codes: issuer.codes, - inputs, - inputs_sum, - script: issuer.script, - signers: issuer.signers, - }) - .collect(), - recipients: recipients - .into_iter() - .map(|TxRecipientTyped { amount, script }| { - (SourceAmount::new(amount as i64, base), script) - }) - .collect(), - user_comment: comment, - } - .gen()?; - - if let Some(final_tx) = final_tx_opt { - Ok(RawTxOrChanges::FinalTx(final_tx.as_text().to_owned())) - } else { - Ok(RawTxOrChanges::Changes( - changes_txs - .into_iter() - .map(|tx| tx.as_text().to_owned()) - .collect(), - )) - } - } else { - Err(async_graphql::Error::new("no blockchain")) - } - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/idty.rs b/rust-libs/modules/gva/gql/src/queries/idty.rs deleted file mode 100644 index ac0090e8c..000000000 --- a/rust-libs/modules/gva/gql/src/queries/idty.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Default)] -pub(crate) struct IdtyQuery; -#[async_graphql::Object] -impl IdtyQuery { - /// Get identity by public key - async fn idty( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "public key")] pubkey: PubKeyGva, - ) -> async_graphql::Result<Option<Identity>> { - let data = ctx.data::<GvaSchemaData>()?; - let dbs_reader = data.dbs_reader(); - - Ok(data - .dbs_pool - .execute(move |dbs| dbs_reader.idty(&dbs.bc_db_ro, pubkey.0)) - .await?? - .map(|idty| Identity { - is_member: idty.is_member, - username: idty.username, - })) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::*; - - #[tokio::test] - async fn test_idty() -> anyhow::Result<()> { - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_idty() - .withf(|_, s| { - s == &PublicKey::from_base58("DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP") - .expect("wrong pubkey") - }) - .times(1) - .returning(|_, _| { - Ok(Some(duniter_dbs::IdtyDbV2 { - is_member: true, - username: String::from("JohnDoe"), - })) - }); - let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?; - assert_eq!( - exec_graphql_request( - &schema, - r#"{ idty(pubkey: "DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP") {isMember, username} }"# - ) - .await?, - serde_json::json!({ - "data": { - "idty": { - "isMember": true, - "username": "JohnDoe" - } - } - }) - ); - Ok(()) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/network.rs b/rust-libs/modules/gva/gql/src/queries/network.rs deleted file mode 100644 index e24be4b4d..000000000 --- a/rust-libs/modules/gva/gql/src/queries/network.rs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Default, async_graphql::SimpleObject)] -pub(crate) struct NetworkQuery { - network: NetworkQueryInner, -} - -#[derive(Default)] -pub(crate) struct NetworkQueryInner; - -#[async_graphql::Object] -impl NetworkQueryInner { - /// Get endpoints known by the node - async fn endpoints( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql( - desc = "filter endpoints by api (exact match endpoint first word, case sensitive)" - )] - api_list: Vec<String>, - ) -> async_graphql::Result<Vec<String>> { - let data = ctx.data::<GvaSchemaData>()?; - let dbs_reader = data.dbs_reader(); - - Ok(data - .dbs_pool - .execute(move |dbs| dbs_reader.endpoints(&dbs.dunp_db, api_list)) - .await??) - } - /// Get peers and heads - async fn nodes( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<Vec<PeerWithHeads>> { - let data = ctx.data::<GvaSchemaData>()?; - - let db_reader = data.dbs_reader(); - - Ok(data - .dbs_pool - .execute(move |dbs| db_reader.peers_and_heads(&dbs.dunp_db)) - .await?? - .into_iter() - .map(|(peer, heads)| PeerWithHeads { - peer: PeerCardGva::from(peer), - heads: heads.into_iter().map(HeadGva::from).collect(), - }) - .collect()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::*; - use duniter_dbs::databases::network_v1::NetworkV1Db; - use pretty_assertions::assert_eq; - - #[tokio::test] - async fn test_endpoints() -> anyhow::Result<()> { - let mock_cm = MockAsyncAccessor::new(); - let mut mock_dbs_reader = MockDbsReader::new(); - mock_dbs_reader - .expect_endpoints::<NetworkV1Db<FileBackend>>() - .times(1) - .returning(|_, _| { - Ok(vec![ - "GVA S g1.librelois.fr 443 gva".to_owned(), - "GVA S domain.tld 443 gva".to_owned(), - ]) - }); - let schema = create_schema(mock_cm, mock_dbs_reader)?; - assert_eq!( - exec_graphql_request(&schema, r#"{ network { endpoints(apiList:["GVA"]) } }"#).await?, - serde_json::json!({ - "data": { - "network": { - "endpoints": [ - "GVA S g1.librelois.fr 443 gva", - "GVA S domain.tld 443 gva" - ] - } - } - }) - ); - Ok(()) - } - - #[tokio::test] - async fn test_peers_and_heads() -> anyhow::Result<()> { - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_peers_and_heads::<NetworkV1Db<FileBackend>>() - .times(1) - .returning(|_| { - Ok(vec![( - duniter_dbs::PeerCardDbV1::default(), - vec![duniter_dbs::DunpHeadDbV1::default()], - )]) - }); - let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?; - assert_eq!( - exec_graphql_request( - &schema, - r#"{ network { nodes { peer { blockstamp }, heads { blockstamp } } } }"# - ) - .await?, - serde_json::json!({ - "data": { - "network": { - "nodes": [ - { - "heads": [ - { - "blockstamp": "0-0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "peer": { - "blockstamp": "" - } - } - ], - } - } - }) - ); - Ok(()) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/txs_history.rs b/rust-libs/modules/gva/gql/src/queries/txs_history.rs deleted file mode 100644 index 3cf5bfe93..000000000 --- a/rust-libs/modules/gva/gql/src/queries/txs_history.rs +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::inputs::TimeInterval; -use crate::*; -use duniter_gva_db::GvaTxDbV1; -use duniter_gva_dbs_reader::txs_history::TxBcCursor; -use futures::future::join; - -#[derive(Default)] -pub(crate) struct TxsHistoryBlockchainQuery; - -#[async_graphql::Object] -impl TxsHistoryBlockchainQuery { - /// Transactions history (written in blockchain) - async fn txs_history_bc( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "pagination", default)] pagination: Pagination, - script: PkOrScriptGva, - #[graphql(default)] time_interval: TimeInterval, - ) -> async_graphql::Result<TxsHistoryBlockchainQueryInner> { - let QueryContext { is_whitelisted } = ctx.data::<QueryContext>()?; - let pagination = Pagination::convert_to_page_info(pagination, *is_whitelisted)?; - let script_hash = Hash::compute(script.0.to_string().as_bytes()); - Ok(TxsHistoryBlockchainQueryInner { - pagination, - script_hash, - time_interval, - }) - } -} - -pub(crate) struct TxsHistoryBlockchainQueryInner { - pub(crate) pagination: PageInfo<TxBcCursor>, - pub(crate) script_hash: Hash, - pub(crate) time_interval: TimeInterval, -} - -#[async_graphql::Object] -impl TxsHistoryBlockchainQueryInner { - /// Transactions history (written in blockchain) - async fn both( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<Connection<String, TxGva, EmptyFields, EdgeTx>> { - let start_time = std::time::Instant::now(); - - let data = ctx.data::<GvaSchemaData>()?; - - let db_reader = data.dbs_reader(); - let pagination = self.pagination; - let script_hash = self.script_hash; - let time_interval = self.time_interval; - let sent_fut = data.dbs_pool.execute(move |_| { - db_reader.get_txs_history_bc_sent( - time_interval.from, - pagination, - script_hash, - time_interval.to, - ) - }); - let db_reader = data.dbs_reader(); - let script_hash = self.script_hash; - let received_fut = data.dbs_pool.execute(move |_| { - db_reader.get_txs_history_bc_received( - time_interval.from, - pagination, - script_hash, - time_interval.to, - ) - }); - let (sent_res, received_res) = join(sent_fut, received_fut).await; - let (sent, received) = (sent_res??, received_res??); - - let mut both_txs = sent - .data - .into_iter() - .map(|db_tx| (TxDirection::Sent, db_tx)) - .chain( - received - .data - .into_iter() - .map(|db_tx| (TxDirection::Received, db_tx)), - ) - .collect::<Vec<(TxDirection, GvaTxDbV1)>>(); - /*if let Some(TxBcCursor { tx_hash, .. }) = pagination.pos() { - while both.txs - }*/ - if self.pagination.order() { - both_txs.sort_unstable_by(|(_, db_tx1), (_, db_tx2)| { - db_tx1 - .written_block - .number - .cmp(&db_tx2.written_block.number) - }); - } else { - both_txs.sort_unstable_by(|(_, db_tx1), (_, db_tx2)| { - db_tx2 - .written_block - .number - .cmp(&db_tx1.written_block.number) - }); - } - if let Some(limit) = self.pagination.limit_opt() { - both_txs.truncate(limit.get()); - } - let mut conn = Connection::new( - sent.has_previous_page || received.has_previous_page, - sent.has_next_page || received.has_next_page, - ); - conn.append(both_txs.into_iter().map(|(tx_direction, db_tx)| { - Edge::with_additional_fields( - TxBcCursor { - block_number: db_tx.written_block.number, - tx_hash: db_tx.tx.get_hash(), - } - .to_string(), - db_tx.into(), - EdgeTx { - direction: tx_direction, - }, - ) - })); - - println!( - "txs_history_bc::both duration: {}ms", - start_time.elapsed().as_millis() - ); - - Ok(conn) - } - /// Received transactions history (written in blockchain) - async fn received( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<Connection<String, TxGva, EmptyFields, EmptyFields>> { - let data = ctx.data::<GvaSchemaData>()?; - let db_reader = data.dbs_reader(); - let pagination = self.pagination; - let script_hash = self.script_hash; - let time_interval = self.time_interval; - let received = data - .dbs_pool - .execute(move |_| { - db_reader.get_txs_history_bc_received( - time_interval.from, - pagination, - script_hash, - time_interval.to, - ) - }) - .await??; - let mut conn = Connection::new(received.has_previous_page, received.has_next_page); - conn.append(received.data.into_iter().map(|db_tx| { - Edge::new( - TxBcCursor { - block_number: db_tx.written_block.number, - tx_hash: db_tx.tx.get_hash(), - } - .to_string(), - db_tx.into(), - ) - })); - - Ok(conn) - } - /// Sent transactions history (written in blockchain) - async fn sent( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<Connection<String, TxGva, EmptyFields, EmptyFields>> { - let data = ctx.data::<GvaSchemaData>()?; - let db_reader = data.dbs_reader(); - let pagination = self.pagination; - let script_hash = self.script_hash; - let time_interval = self.time_interval; - let sent = data - .dbs_pool - .execute(move |_| { - db_reader.get_txs_history_bc_sent( - time_interval.from, - pagination, - script_hash, - time_interval.to, - ) - }) - .await??; - let mut conn = Connection::new(sent.has_previous_page, sent.has_next_page); - conn.append(sent.data.into_iter().map(|db_tx| { - Edge::new( - TxBcCursor { - block_number: db_tx.written_block.number, - tx_hash: db_tx.tx.get_hash(), - } - .to_string(), - db_tx.into(), - ) - })); - - Ok(conn) - } -} - -#[derive(Default)] -pub(crate) struct TxsHistoryMempoolQuery; - -#[async_graphql::Object] -impl TxsHistoryMempoolQuery { - /// Transactions waiting on mempool - async fn txs_history_mp( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "Ed25519 public key on base 58 representation")] pubkey: PubKeyGva, - ) -> async_graphql::Result<TxsHistoryMempool> { - let data = ctx.data::<GvaSchemaData>()?; - let db_reader = data.dbs_reader(); - - let (sending, pending) = data - .dbs_pool - .execute(move |dbs| db_reader.get_txs_history_mempool(&dbs.txs_mp_db, pubkey.0)) - .await??; - - Ok(TxsHistoryMempool { - sending: sending - .into_iter() - .map(|db_tx| TxGva::from(&db_tx)) - .collect(), - receiving: pending - .into_iter() - .map(|db_tx| TxGva::from(&db_tx)) - .collect(), - }) - } -} - -#[cfg(test)] -mod tests { - use std::collections::VecDeque; - - use crate::tests::*; - use dubp::documents::transaction::TransactionDocumentV10; - use dubp::documents::transaction::TransactionDocumentV10Stringified; - use dubp::documents_parser::prelude::FromStringObject; - use duniter_gva_db::GvaTxDbV1; - use duniter_gva_dbs_reader::pagination::PagedData; - - #[tokio::test] - async fn test_txs_history_blockchain() -> anyhow::Result<()> { - let mut dbs_reader = MockDbsReader::new(); - dbs_reader - .expect_get_txs_history_bc_received() - .times(1) - .returning(|_, _, _, _| Ok(PagedData::empty())); - dbs_reader - .expect_get_txs_history_bc_sent() - .times(1) - .returning(|_, _, _, _| { - let tx = TransactionDocumentV10::from_string_object( - &TransactionDocumentV10Stringified { - currency: "test".to_owned(), - blockstamp: - "0-0000000000000000000000000000000000000000000000000000000000000000" - .to_owned(), - locktime: 0, - issuers: vec![], - inputs: vec![], - unlocks: vec![], - outputs: vec![], - comment: "".to_owned(), - signatures: vec![], - hash: Some( - "0000000000000000000000000000000000000000000000000000000000000000" - .to_owned(), - ), - }, - ) - .expect("wrong tx"); - let mut expected_data = VecDeque::new(); - expected_data.push_back(GvaTxDbV1 { - tx, - ..Default::default() - }); - Ok(PagedData { - data: expected_data, - has_previous_page: false, - has_next_page: false, - }) - }); - let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?; - assert_eq!( - exec_graphql_request( - &schema, - r#"{ - txsHistoryBc(script: "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx") { - sent { - edges { - node { - blockstamp - } - } - } - received { - edges { - node { - blockstamp - } - } - } - } - }"# - ) - .await?, - serde_json::json!({ - "data": { - "txsHistoryBc": { - "received": { - "edges": [] - }, - "sent": { - "edges": [{ - "node": { - "blockstamp": "0-0000000000000000000000000000000000000000000000000000000000000000", - } - }] - } - } - } - }) - ); - Ok(()) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/uds.rs b/rust-libs/modules/gva/gql/src/queries/uds.rs deleted file mode 100644 index a3eab34c1..000000000 --- a/rust-libs/modules/gva/gql/src/queries/uds.rs +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use async_graphql::connection::*; -use duniter_dbs::databases::bc_v2::BcV2DbReadable; -use duniter_gva_dbs_reader::{uds_of_pubkey::UdsWithSum, PagedData}; - -#[derive(Default)] -pub(crate) struct UdsQuery; -#[async_graphql::Object] -impl UdsQuery { - /// Current universal dividends amount - async fn current_ud( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<Option<CurrentUdGva>> { - let data = ctx.data::<GvaSchemaData>()?; - - Ok( - if let Some(current_ud) = data.cm_accessor.get_current_meta(|cm| cm.current_ud).await { - Some(CurrentUdGva { - amount: current_ud.amount(), - base: current_ud.base(), - }) - } else { - None - }, - ) - } - /// Universal dividends issued by a public key - #[allow(clippy::clippy::too_many_arguments)] - async fn uds_of_pubkey( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "Ed25519 public key on base 58 representation")] pubkey: PubKeyGva, - #[graphql(default)] filter: UdsFilter, - #[graphql(desc = "pagination", default)] pagination: Pagination, - #[graphql(desc = "Amount needed")] amount: Option<i64>, - ) -> async_graphql::Result<Connection<String, UdGva, AggregateSum, EmptyFields>> { - let QueryContext { is_whitelisted } = ctx.data::<QueryContext>()?; - let pagination = Pagination::convert_to_page_info(pagination, *is_whitelisted)?; - - let data = ctx.data::<GvaSchemaData>()?; - let dbs_reader = data.dbs_reader(); - - if let Some(current_base) = data - .cm_accessor - .get_current_meta(|cm| cm.current_block_meta.unit_base) - .await - { - let ( - PagedData { - data: UdsWithSum { uds, sum }, - has_previous_page, - has_next_page, - }, - times, - ) = data - .dbs_pool - .execute(move |dbs| { - let paged_data = match filter { - UdsFilter::All => { - dbs_reader.all_uds_of_pubkey(&dbs.bc_db_ro, pubkey.0, pagination) - } - UdsFilter::Unspent => dbs_reader.unspent_uds_of_pubkey( - &dbs.bc_db_ro, - pubkey.0, - pagination, - None, - amount.map(|amount| SourceAmount::new(amount, current_base as i64)), - ), - }?; - - let mut times = Vec::with_capacity(paged_data.data.uds.len()); - for (bn, _sa) in &paged_data.data.uds { - times.push(dbs_reader.get_blockchain_time(*bn)?); - } - Ok::<_, anyhow::Error>((paged_data, times)) - }) - .await??; - - let mut conn = Connection::with_additional_fields( - has_previous_page, - has_next_page, - AggregateSum { - aggregate: Sum { - sum: AmountWithBase { - amount: sum.amount() as i32, - base: sum.base() as i32, - }, - }, - }, - ); - let uds_timed = - uds.into_iter() - .zip(times.into_iter()) - .map(|((bn, sa), blockchain_time)| { - Edge::new( - bn.0.to_string(), - UdGva { - amount: sa.amount(), - base: sa.base(), - issuer: pubkey, - block_number: bn.0, - blockchain_time, - }, - ) - }); - if pagination.order() { - conn.append(uds_timed); - } else { - conn.append(uds_timed.rev()); - } - Ok(conn) - } else { - Err(async_graphql::Error::new("no blockchain")) - } - } - /// Universal dividends revaluations - async fn uds_reval( - &self, - ctx: &async_graphql::Context<'_>, - ) -> async_graphql::Result<Vec<RevalUdGva>> { - let data = ctx.data::<GvaSchemaData>()?; - - Ok(data - .dbs_pool - .execute(move |dbs| { - dbs.bc_db_ro.uds_reval().iter(.., |it| { - it.map_ok(|(block_number, sa)| RevalUdGva { - amount: sa.0.amount(), - base: sa.0.base(), - block_number: block_number.0, - }) - .collect::<KvResult<Vec<_>>>() - }) - }) - .await??) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::*; - - #[tokio::test] - async fn query_current_ud() -> anyhow::Result<()> { - let mut mock_cm = MockAsyncAccessor::new(); - mock_cm - .expect_get_current_meta::<SourceAmount>() - .times(1) - .returning(|f| { - Some(f(&CurrentMeta { - current_ud: SourceAmount::with_base0(100), - ..Default::default() - })) - }); - let schema = create_schema(mock_cm, MockDbsReader::new())?; - assert_eq!( - exec_graphql_request(&schema, r#"{ currentUd {amount} }"#).await?, - serde_json::json!({ - "data": { - "currentUd": { - "amount": 100 - } - } - }) - ); - Ok(()) - } -} diff --git a/rust-libs/modules/gva/gql/src/queries/utxos_of_script.rs b/rust-libs/modules/gva/gql/src/queries/utxos_of_script.rs deleted file mode 100644 index c3a3039e5..000000000 --- a/rust-libs/modules/gva/gql/src/queries/utxos_of_script.rs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use async_graphql::connection::*; -use duniter_gva_dbs_reader::{ - utxos::{UtxoCursor, UtxosWithSum}, - PagedData, -}; - -#[derive(Default)] -pub(crate) struct UtxosQuery; -#[async_graphql::Object] -impl UtxosQuery { - /// Utxos of script - async fn utxos_of_script( - &self, - ctx: &async_graphql::Context<'_>, - #[graphql(desc = "DUBP wallet script")] script: PkOrScriptGva, - #[graphql(desc = "pagination", default)] pagination: Pagination, - #[graphql(desc = "Amount needed")] amount: Option<i64>, - ) -> async_graphql::Result<Connection<String, UtxoTimedGva, AggregateSum, EmptyFields>> { - let QueryContext { is_whitelisted } = ctx.data::<QueryContext>()?; - log::info!("is_whitelisted={}", is_whitelisted); - let pagination = Pagination::convert_to_page_info(pagination, *is_whitelisted)?; - - let data = ctx.data::<GvaSchemaData>()?; - let cm_accessor = data.cm_accessor(); - let db_reader = data.dbs_reader(); - - if let Some(current_base) = cm_accessor - .get_current_meta(|cm| cm.current_block_meta.unit_base) - .await - { - let ( - PagedData { - data: UtxosWithSum { utxos, sum }, - has_previous_page, - has_next_page, - }, - times, - ) = data - .dbs_pool - .execute(move |dbs| { - let paged_data = db_reader.find_script_utxos( - &dbs.txs_mp_db, - amount.map(|amount| SourceAmount::new(amount, current_base as i64)), - pagination, - &script.0, - )?; - let mut times = Vec::with_capacity(paged_data.data.utxos.len()); - for (UtxoCursor { block_number, .. }, _sa) in &paged_data.data.utxos { - times.push(db_reader.get_blockchain_time(*block_number)?); - } - Ok::<_, anyhow::Error>((paged_data, times)) - }) - .await??; - - let mut conn = Connection::with_additional_fields( - has_previous_page, - has_next_page, - AggregateSum { - aggregate: Sum { - sum: AmountWithBase { - amount: sum.amount() as i32, - base: sum.base() as i32, - }, - }, - }, - ); - conn.append(utxos.into_iter().zip(times.into_iter()).map( - |((utxo_cursor, source_amount), blockchain_time)| { - Edge::new( - utxo_cursor.to_string(), - UtxoTimedGva { - amount: source_amount.amount(), - base: source_amount.base(), - tx_hash: utxo_cursor.tx_hash.to_hex(), - output_index: utxo_cursor.output_index as u32, - written_block: utxo_cursor.block_number.0, - written_time: blockchain_time, - }, - ) - }, - )); - Ok(conn) - } else { - Err(async_graphql::Error::new("no blockchain")) - } - } -} diff --git a/rust-libs/modules/gva/gql/src/scalars.rs b/rust-libs/modules/gva/gql/src/scalars.rs deleted file mode 100644 index f58a79ba5..000000000 --- a/rust-libs/modules/gva/gql/src/scalars.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use async_graphql::{InputValueError, InputValueResult, Scalar, ScalarType}; -use dubp::crypto::bases::b58::ToBase58; - -#[derive(Clone, Copy, Debug)] -pub(crate) struct PubKeyGva(pub(crate) PublicKey); - -impl async_graphql::Description for PubKeyGva { - fn description() -> &'static str { - "Public key on base 58 representation" - } -} - -#[Scalar(use_type_description = true)] -impl ScalarType for PubKeyGva { - fn parse(value: async_graphql::Value) -> InputValueResult<Self> { - if let async_graphql::Value::String(value_str) = &value { - if value_str.len() < 40 { - Err(InputValueError::custom("too short public key")) - } else if value_str.len() > 44 { - Err(InputValueError::custom("too long public key")) - } else { - Ok(PublicKey::from_base58(value_str).map(PubKeyGva)?) - } - } else { - // If the type does not match - Err(InputValueError::expected_type(value)) - } - } - - fn to_value(&self) -> async_graphql::Value { - async_graphql::Value::String(self.0.to_base58()) - } -} - -pub(crate) struct PkOrScriptGva(pub(crate) WalletScriptV10); - -impl async_graphql::Description for PkOrScriptGva { - fn description() -> &'static str { - "Public key on base 58 representation or complex DUBP script" - } -} - -#[Scalar(use_type_description = true)] -impl ScalarType for PkOrScriptGva { - fn parse(value: async_graphql::Value) -> InputValueResult<Self> { - if let async_graphql::Value::String(value_str) = &value { - Ok(PkOrScriptGva( - if value_str.len() >= 40 || value_str.len() <= 44 { - if let Ok(pubkey) = PublicKey::from_base58(&value_str) { - WalletScriptV10::single_sig(pubkey) - } else { - dubp::documents_parser::wallet_script_from_str(&value_str)? - } - } else { - dubp::documents_parser::wallet_script_from_str(&value_str)? - }, - )) - } else { - // If the type does not match - Err(InputValueError::expected_type(value)) - } - } - - fn to_value(&self) -> async_graphql::Value { - async_graphql::Value::String(self.0.to_string()) - } -} diff --git a/rust-libs/modules/gva/gql/src/schema.rs b/rust-libs/modules/gva/gql/src/schema.rs deleted file mode 100644 index c5ab4f6de..000000000 --- a/rust-libs/modules/gva/gql/src/schema.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub type GvaSchema = async_graphql::Schema< - crate::queries::QueryRoot, - crate::mutations::MutationRoot, - crate::subscriptions::SubscriptionRoot, ->; - -pub fn get_schema_definition() -> String { - async_graphql::Schema::build( - queries::QueryRoot::default(), - mutations::MutationRoot::default(), - subscriptions::SubscriptionRoot::default(), - ) - .finish() - .sdl() -} - -pub fn build_schema_with_data(data: GvaSchemaData, logger: bool) -> GvaSchema { - let mut builder = async_graphql::Schema::build( - queries::QueryRoot::default(), - mutations::MutationRoot::default(), - subscriptions::SubscriptionRoot::default(), - ) - .data(data); - if logger { - builder = builder.extension(async_graphql::extensions::Logger); - } - builder.finish() -} - -pub struct GvaSchemaData { - pub cm_accessor: AsyncAccessor, - pub dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - pub dbs_reader: DbsReaderImpl, - pub server_meta_data: ServerMetaData, - pub txs_mempool: TxsMempool, -} - -#[cfg(not(test))] -impl GvaSchemaData { - #[inline(always)] - pub fn cm_accessor(&self) -> AsyncAccessor { - self.cm_accessor - } - #[inline(always)] - pub fn dbs_reader(&self) -> DbsReaderImpl { - self.dbs_reader - } -} -#[cfg(test)] -impl GvaSchemaData { - pub fn cm_accessor(&self) -> AsyncAccessor { - self.cm_accessor.clone() - } - pub fn dbs_reader(&self) -> DbsReaderImpl { - self.dbs_reader.clone() - } -} diff --git a/rust-libs/modules/gva/gql/src/subscriptions.rs b/rust-libs/modules/gva/gql/src/subscriptions.rs deleted file mode 100644 index 4a5dafaa6..000000000 --- a/rust-libs/modules/gva/gql/src/subscriptions.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -mod new_blocks; -mod receive_pending_txs; - -use crate::*; -use futures::future::Either; - -#[derive(Clone, Copy, Default, async_graphql::MergedSubscription)] -pub struct SubscriptionRoot( - new_blocks::NewBlocksSubscription, - receive_pending_txs::PendingTxsSubscription, -); - -pub(crate) async fn create_subscription<C, D, E, F, FC, FUT>( - ctx: &async_graphql::Context<'_>, - select_col: FC, - f: F, -) -> impl Stream<Item = async_graphql::Result<D>> -where - C: DbCollectionRo<Event = E, K = E::K, V = E::V>, - E: EventTrait, - F: FnMut(Arc<Events<E>>) -> FUT, - FUT: std::future::Future<Output = Option<async_graphql::Result<D>>>, - FC: 'static + Send + FnOnce(&SharedDbs<FileBackend>) -> &C, -{ - match subscribe_to_col(ctx, select_col).await { - Ok(r) => Either::Left(r.into_stream().filter_map(f)), - Err(e) => { - use futures::FutureExt; - Either::Right(futures::future::ready(Err(e)).into_stream()) - } - } -} - -async fn subscribe_to_col<C, E, F>( - ctx: &async_graphql::Context<'_>, - f: F, -) -> async_graphql::Result<flume::Receiver<Arc<Events<E>>>> -where - C: DbCollectionRo<Event = E, K = E::K, V = E::V>, - E: EventTrait, - F: 'static + Send + FnOnce(&SharedDbs<FileBackend>) -> &C, -{ - let data = ctx.data::<GvaSchemaData>()?; - let (s, r) = flume::unbounded(); - data.dbs_pool.execute(|dbs| f(dbs).subscribe(s)).await??; - Ok(r) -} diff --git a/rust-libs/modules/gva/gql/src/subscriptions/new_blocks.rs b/rust-libs/modules/gva/gql/src/subscriptions/new_blocks.rs deleted file mode 100644 index aa6c56e34..000000000 --- a/rust-libs/modules/gva/gql/src/subscriptions/new_blocks.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use super::create_subscription; -use crate::*; -use duniter_dbs::databases::cm_v1::{CmV1DbReadable, CurrentBlockEvent}; - -#[derive(Clone, Copy, Default)] -pub struct NewBlocksSubscription; - -#[async_graphql::Subscription] -impl NewBlocksSubscription { - async fn new_blocks( - &self, - ctx: &async_graphql::Context<'_>, - ) -> impl Stream<Item = async_graphql::Result<Vec<Block>>> { - create_subscription( - ctx, - |dbs| dbs.cm_db.current_block(), - |events| { - let mut blocks = Vec::new(); - for event in events.deref() { - if let CurrentBlockEvent::Upsert { - value: ref block, .. - } = event - { - blocks.push(Block::from(&block.0)); - } - } - if blocks.is_empty() { - futures::future::ready(None) - } else { - futures::future::ready(Some(Ok(blocks))) - } - }, - ) - .await - } -} diff --git a/rust-libs/modules/gva/gql/src/subscriptions/receive_pending_txs.rs b/rust-libs/modules/gva/gql/src/subscriptions/receive_pending_txs.rs deleted file mode 100644 index 232822866..000000000 --- a/rust-libs/modules/gva/gql/src/subscriptions/receive_pending_txs.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use super::create_subscription; -use crate::*; -use duniter_dbs::databases::txs_mp_v2::TxsEvent; - -#[derive(Clone, Copy, Default)] -pub struct PendingTxsSubscription; - -#[async_graphql::Subscription] -impl PendingTxsSubscription { - async fn receive_pending_txs( - &self, - ctx: &async_graphql::Context<'_>, - ) -> impl Stream<Item = async_graphql::Result<Vec<TxGva>>> { - create_subscription( - ctx, - |dbs| dbs.txs_mp_db.txs(), - |events| { - let mut txs = Vec::new(); - for event in events.deref() { - if let TxsEvent::Upsert { - value: ref pending_tx, - .. - } = event - { - txs.push(TxGva::from(&pending_tx.0)); - } - } - if txs.is_empty() { - futures::future::ready(None) - } else { - futures::future::ready(Some(Ok(txs))) - } - }, - ) - .await - } -} diff --git a/rust-libs/modules/gva/indexer/Cargo.toml b/rust-libs/modules/gva/indexer/Cargo.toml deleted file mode 100644 index 966ffef15..000000000 --- a/rust-libs/modules/gva/indexer/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "duniter-gva-indexer" -version = "0.1.0" -authors = ["elois <elois@duniter.org>"] -description = "Duniter GVA DB writer" -repository = "https://git.duniter.org/nodes/typescript/duniter" -keywords = ["dubp", "duniter", "blockchain", "database"] -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -anyhow = "1.0.34" -duniter-dbs = { path = "../../../duniter-dbs" } -duniter-gva-db = { path = "../db" } -dubp = { version = "0.51.0", features = ["duniter"] } -once_cell = "1.5.2" -resiter = "0.4.0" - -[dev-dependencies] -duniter-dbs = { path = "../../../duniter-dbs", features = ["mem"] } -maplit = "1.0.2" -smallvec = { version = "1.4.0", features = ["serde", "write"] } diff --git a/rust-libs/modules/gva/indexer/src/identities.rs b/rust-libs/modules/gva/indexer/src/identities.rs deleted file mode 100644 index 0a33b376b..000000000 --- a/rust-libs/modules/gva/indexer/src/identities.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub(crate) fn update_identities<B: Backend>( - block: &DubpBlockV10, - identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>, -) -> KvResult<()> { - for mb in block.joiners() { - let pubkey = mb.issuers()[0]; - - let mut idty = identities.get(&PubKeyKeyV2(pubkey))?.unwrap_or_default(); - idty.is_member = true; - idty.joins.push(block.number()); - identities.upsert(PubKeyKeyV2(pubkey), idty); - } - for revo in block.revoked() { - let pubkey = revo.issuer; - if let Some(mut idty) = identities.get(&PubKeyKeyV2(pubkey))? { - idty.is_member = false; - idty.leaves.insert(block.number()); - identities.upsert(PubKeyKeyV2(pubkey), idty) - } - } - for pubkey in block.excluded().iter().copied() { - if let Some(mut idty) = identities.get(&PubKeyKeyV2(pubkey))? { - idty.is_member = false; - idty.leaves.insert(block.number()); - identities.upsert(PubKeyKeyV2(pubkey), idty) - } - } - Ok(()) -} - -pub(crate) fn revert_identities<B: Backend>( - block: &DubpBlockV10, - identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>, -) -> KvResult<()> { - for mb in block.joiners() { - let pubkey = mb.issuers()[0]; - - let mut idty = identities.get(&PubKeyKeyV2(pubkey))?.unwrap_or_default(); - idty.is_member = false; - idty.joins.pop(); - identities.upsert(PubKeyKeyV2(pubkey), idty); - } - for idty in block.identities() { - let pubkey = idty.issuers()[0]; - identities.remove(PubKeyKeyV2(pubkey)); - } - for revo in block.revoked() { - let pubkey = revo.issuer; - if let Some(mut idty) = identities.get(&PubKeyKeyV2(pubkey))? { - idty.is_member = true; - idty.leaves.remove(&block.number()); - identities.upsert(PubKeyKeyV2(pubkey), idty) - } - } - for pubkey in block.excluded().iter().copied() { - if let Some(mut idty) = identities.get(&PubKeyKeyV2(pubkey))? { - idty.is_member = true; - idty.leaves.remove(&block.number()); - identities.upsert(PubKeyKeyV2(pubkey), idty) - } - } - Ok(()) -} diff --git a/rust-libs/modules/gva/indexer/src/lib.rs b/rust-libs/modules/gva/indexer/src/lib.rs deleted file mode 100644 index 333e1981e..000000000 --- a/rust-libs/modules/gva/indexer/src/lib.rs +++ /dev/null @@ -1,593 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -mod identities; -mod tx; -mod utxos; - -use dubp::block::prelude::*; -use dubp::common::crypto::hashs::Hash; -use dubp::common::prelude::*; -use dubp::documents::{ - prelude::*, transaction::TransactionDocumentTrait, transaction::TransactionDocumentV10, -}; -use dubp::wallet::prelude::*; -use duniter_dbs::{ - kv_typed::prelude::*, prelude::*, FileBackend, HashKeyV2, PubKeyKeyV2, SourceAmountValV2, - WalletConditionsV2, -}; -use duniter_gva_db::*; -use resiter::filter::Filter; -use std::{ - collections::{BTreeSet, HashMap}, - path::Path, -}; - -static GVA_DB_RO: once_cell::sync::OnceCell<GvaV1DbRo<FileBackend>> = - once_cell::sync::OnceCell::new(); -static GVA_DB_RW: once_cell::sync::OnceCell<GvaV1Db<FileBackend>> = - once_cell::sync::OnceCell::new(); - -pub fn get_gva_db_ro(profile_path_opt: Option<&Path>) -> &'static GvaV1DbRo<FileBackend> { - GVA_DB_RO.get_or_init(|| get_gva_db_rw(profile_path_opt).get_ro_handler()) -} -pub fn get_gva_db_rw(profile_path_opt: Option<&Path>) -> &'static GvaV1Db<FileBackend> { - GVA_DB_RW.get_or_init(|| { - duniter_gva_db::GvaV1Db::<FileBackend>::open(FileBackend::gen_backend_conf( - "gva_v1", - profile_path_opt, - )) - .expect("Fail to open GVA DB") - }) -} - -pub struct UtxoV10<'s> { - pub id: UtxoIdV10, - pub amount: SourceAmount, - pub script: &'s WalletScriptV10, - pub written_block: BlockNumber, -} - -pub fn apply_block<B: Backend>(block: &DubpBlockV10, gva_db: &GvaV1Db<B>) -> KvResult<()> { - let blockstamp = Blockstamp { - number: block.number(), - hash: block.hash(), - }; - gva_db.write(|mut db| { - db.blocks_by_common_time - .upsert(U64BE(block.common_time()), block.number().0); - db.blockchain_time - .upsert(U32BE(block.number().0), block.common_time()); - identities::update_identities::<B>(&block, &mut db.gva_identities)?; - if let Some(divident_amount) = block.dividend() { - db.blocks_with_ud.upsert(U32BE(blockstamp.number.0), ()); - apply_ud::<B>( - blockstamp.number, - divident_amount, - &mut db.balances, - &mut db.gva_identities, - )?; - } - apply_block_txs::<B>( - &mut db, - blockstamp, - block.common_time() as i64, - block.transactions(), - ) - })?; - - Ok(()) -} - -pub fn revert_block<B: Backend>(block: &DubpBlockV10, gva_db: &GvaV1Db<B>) -> KvResult<()> { - gva_db.write(|mut db| { - db.blocks_by_common_time.remove(U64BE(block.common_time())); - db.blockchain_time.remove(U32BE(block.number().0)); - identities::revert_identities::<B>(&block, &mut db.gva_identities)?; - if let Some(divident_amount) = block.dividend() { - db.blocks_with_ud.remove(U32BE(block.number().0)); - revert_ud::<B>( - block.number(), - divident_amount, - &mut db.balances, - &mut db.gva_identities, - )?; - } - - let mut scripts_hash = HashMap::with_capacity(block.transactions().len() * 3); - for tx in block.transactions() { - let tx_hash = tx.get_hash(); - tx::revert_tx::<B>(block.number(), &mut db, &mut scripts_hash, &tx_hash)?.ok_or_else( - || { - KvError::DbCorrupted(format!( - "GVA: tx '{}' dont exist on txs history.", - tx_hash, - )) - }, - )?; - } - db.txs_by_block.remove(U32BE(block.number().0)); - Ok(()) - })?; - - Ok(()) -} - -fn apply_ud<B: Backend>( - block_number: BlockNumber, - divident_amount: SourceAmount, - balances: &mut TxColRw<B::Col, BalancesEvent>, - identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>, -) -> KvResult<()> { - let members = identities.iter(.., |it| { - it.filter_ok(|(_pk, idty)| idty.is_member) - .collect::<KvResult<Vec<_>>>() - })?; - for (pk, mut idty) in members { - if idty.first_ud.is_none() { - idty.first_ud = Some(block_number); - identities.upsert(pk, idty); - } - - // Increase account balance - let account_script = WalletScriptV10::single_sig(pk.0); - let balance = balances - .get(WalletConditionsV2::from_ref(&account_script))? - .unwrap_or_default(); - balances.upsert( - WalletConditionsV2(account_script), - SourceAmountValV2(balance.0 + divident_amount), - ); - } - Ok(()) -} - -fn revert_ud<B: Backend>( - block_number: BlockNumber, - divident_amount: SourceAmount, - balances: &mut TxColRw<B::Col, BalancesEvent>, - identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>, -) -> KvResult<()> { - let members = identities.iter(.., |it| { - it.filter_ok(|(_pk, idty)| idty.is_member) - .collect::<KvResult<Vec<_>>>() - })?; - for (pk, mut idty) in members { - if let Some(first_ud) = idty.first_ud { - if first_ud == block_number { - idty.first_ud = None; - identities.upsert(pk, idty); - } - } - - // Increase account balance - let account_script = WalletScriptV10::single_sig(pk.0); - if let Some(SourceAmountValV2(balance)) = - balances.get(WalletConditionsV2::from_ref(&account_script))? - { - balances.upsert( - WalletConditionsV2(account_script), - SourceAmountValV2(balance - divident_amount), - ); - } - } - Ok(()) -} - -fn apply_block_txs<B: Backend>( - gva_db: &mut GvaV1DbTxRw<B::Col>, - current_blockstamp: Blockstamp, - current_time: i64, - txs: &[TransactionDocumentV10], -) -> KvResult<()> { - let mut scripts_index = HashMap::new(); - let mut txs_by_issuer_mem = HashMap::new(); - let mut txs_by_recipient_mem = HashMap::new(); - let mut txs_hashes = Vec::with_capacity(txs.len()); - for tx in txs { - let tx_hash = tx.get_hash(); - txs_hashes.push(tx_hash); - // Write tx and update sources - tx::apply_tx::<B>( - current_blockstamp, - current_time, - gva_db, - &mut scripts_index, - tx_hash, - tx, - &mut txs_by_issuer_mem, - &mut txs_by_recipient_mem, - )?; - } - - if !txs_hashes.is_empty() { - gva_db - .txs_by_block - .upsert(U32BE(current_blockstamp.number.0), txs_hashes); - } - for (k, v) in txs_by_issuer_mem { - gva_db.txs_by_issuer.upsert(k, v); - } - for (k, v) in txs_by_recipient_mem { - gva_db.txs_by_recipient.upsert(k, v); - } - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - use dubp::{ - crypto::keys::{ed25519::PublicKey, PublicKey as _}, - documents::transaction::TransactionDocumentV10Stringified, - documents_parser::prelude::FromStringObject, - }; - - #[test] - fn test_gva_apply_block() -> anyhow::Result<()> { - let gva_db = GvaV1Db::<Mem>::open(MemConf::default())?; - - let s1 = WalletScriptV10::single_sig(PublicKey::from_base58( - "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx", - )?); - let s2 = WalletScriptV10::single_sig(PublicKey::from_base58( - "4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m", - )?); - - let b0 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - version: 10, - median_time: 5_243, - dividend: Some(1000), - joiners: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&b0, &gva_db)?; - - assert_eq!(gva_db.blocks_by_common_time().count()?, 1); - assert_eq!(gva_db.blocks_by_common_time().get(&U64BE(5_243))?, Some(0)); - assert_eq!(gva_db.blockchain_time().count()?, 1); - assert_eq!(gva_db.blockchain_time().get(&U32BE(0))?, Some(5_243)); - assert_eq!(gva_db.balances().count()?, 1); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s1.clone()))?, - Some(SourceAmountValV2(SourceAmount::with_base0(1000))) - ); - assert_eq!(gva_db.txs_by_block().count()?, 0); - - let b1 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - number: 1, - version: 10, - median_time: 5_245, - transactions: vec![TransactionDocumentV10Stringified { - currency: "test".to_owned(), - blockstamp: "0-0000000000000000000000000000000000000000000000000000000000000000".to_owned(), - locktime: 0, - issuers: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx".to_owned()], - inputs: vec!["1000:0:D:D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:0".to_owned()], - unlocks: vec![], - outputs: vec![ - "600:0:SIG(4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m)".to_owned(), - "400:0:SIG(D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx)".to_owned(), - ], - comment: "".to_owned(), - signatures: vec![], - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - }], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&b1, &gva_db)?; - - assert_eq!(gva_db.blocks_by_common_time().count()?, 2); - assert_eq!(gva_db.blocks_by_common_time().get(&U64BE(5_245))?, Some(1)); - assert_eq!(gva_db.blockchain_time().count()?, 2); - assert_eq!(gva_db.blockchain_time().get(&U32BE(1))?, Some(5_245)); - assert_eq!(gva_db.balances().count()?, 2); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s2.clone()))?, - Some(SourceAmountValV2(SourceAmount::with_base0(600))) - ); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s1.clone()))?, - Some(SourceAmountValV2(SourceAmount::with_base0(400))) - ); - assert_eq!(gva_db.gva_utxos().count()?, 2); - assert_eq!( - gva_db - .gva_utxos() - .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, - vec![ - ( - GvaUtxoIdDbV1::new(s1.clone(), 1, Hash::default(), 1), - SourceAmountValV2(SourceAmount::with_base0(400)) - ), - ( - GvaUtxoIdDbV1::new(s2.clone(), 1, Hash::default(), 0), - SourceAmountValV2(SourceAmount::with_base0(600)) - ), - ] - ); - assert_eq!(gva_db.txs_by_block().count()?, 1); - assert_eq!( - gva_db.txs_by_block().get(&U32BE(1))?, - Some(vec![Hash::from_hex( - "0000000000000000000000000000000000000000000000000000000000000000" - )?]) - ); - - let b2 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - number: 2, - version: 10, - median_time: 5_247, - transactions: vec![TransactionDocumentV10Stringified { - currency: "test".to_owned(), - blockstamp: "0-0000000000000000000000000000000000000000000000000000000000000000".to_owned(), - locktime: 0, - issuers: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx".to_owned()], - inputs: vec!["400:0:T:0000000000000000000000000000000000000000000000000000000000000000:1".to_owned()], - unlocks: vec![], - outputs: vec![ - "300:0:SIG(D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx)".to_owned(), - "100:0:SIG(4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m)".to_owned(), - ], - comment: "".to_owned(), - signatures: vec![], - hash: Some("0101010101010101010101010101010101010101010101010101010101010101".to_owned()), - }], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&b2, &gva_db)?; - - assert_eq!(gva_db.blocks_by_common_time().count()?, 3); - assert_eq!(gva_db.blocks_by_common_time().get(&U64BE(5_247))?, Some(2)); - assert_eq!(gva_db.blockchain_time().count()?, 3); - assert_eq!(gva_db.blockchain_time().get(&U32BE(2))?, Some(5_247)); - assert_eq!(gva_db.balances().count()?, 2); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s2.clone()))?, - Some(SourceAmountValV2(SourceAmount::with_base0(700))) - ); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s1.clone()))?, - Some(SourceAmountValV2(SourceAmount::with_base0(300))) - ); - assert_eq!(gva_db.gva_utxos().count()?, 3); - assert_eq!( - gva_db - .gva_utxos() - .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, - vec![ - ( - GvaUtxoIdDbV1::new(s1, 2, Hash([1; 32]), 0), - SourceAmountValV2(SourceAmount::with_base0(300)) - ), - ( - GvaUtxoIdDbV1::new(s2.clone(), 1, Hash::default(), 0), - SourceAmountValV2(SourceAmount::with_base0(600)) - ), - ( - GvaUtxoIdDbV1::new(s2, 2, Hash([1; 32]), 1), - SourceAmountValV2(SourceAmount::with_base0(100)) - ), - ] - ); - assert_eq!(gva_db.txs_by_block().count()?, 2); - assert_eq!( - gva_db.txs_by_block().get(&U32BE(2))?, - Some(vec![Hash::from_hex( - "0101010101010101010101010101010101010101010101010101010101010101" - )?]) - ); - - Ok(()) - } - - #[test] - fn test_gva_revert_block() -> anyhow::Result<()> { - let gva_db = GvaV1Db::<Mem>::open(MemConf::default())?; - - let s1 = WalletScriptV10::single_sig(PublicKey::from_base58( - "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx", - )?); - let s2 = WalletScriptV10::single_sig(PublicKey::from_base58( - "4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m", - )?); - - let b0 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - version: 10, - median_time: 5_243, - dividend: Some(1000), - joiners: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&b0, &gva_db)?; - - let b1 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - number: 1, - version: 10, - median_time: 5_245, - transactions: vec![TransactionDocumentV10Stringified { - currency: "test".to_owned(), - blockstamp: "0-0000000000000000000000000000000000000000000000000000000000000000".to_owned(), - locktime: 0, - issuers: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx".to_owned()], - inputs: vec!["1000:0:D:D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:0".to_owned()], - unlocks: vec![], - outputs: vec![ - "600:0:SIG(4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m)".to_owned(), - "400:0:SIG(D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx)".to_owned(), - ], - comment: "".to_owned(), - signatures: vec![], - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - }], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&b1, &gva_db)?; - - let b2 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - number: 2, - version: 10, - median_time: 5_247, - transactions: vec![TransactionDocumentV10Stringified { - currency: "test".to_owned(), - blockstamp: "0-0000000000000000000000000000000000000000000000000000000000000000".to_owned(), - locktime: 0, - issuers: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx".to_owned()], - inputs: vec!["400:0:T:0000000000000000000000000000000000000000000000000000000000000000:1".to_owned()], - unlocks: vec![], - outputs: vec![ - "400:0:SIG(4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m)".to_owned(), - ], - comment: "".to_owned(), - signatures: vec![], - hash: Some("0101010101010101010101010101010101010101010101010101010101010101".to_owned()), - }], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&b2, &gva_db)?; - - let b3 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { - number: 3, - version: 10, - median_time: 5_249, - transactions: vec![TransactionDocumentV10Stringified { - currency: "test".to_owned(), - blockstamp: "0-0000000000000000000000000000000000000000000000000000000000000000".to_owned(), - locktime: 0, - issuers: vec!["4fHMTFBMo5sTQEc5p1CNWz28S4mnnqdUBmECq1zt4n2m".to_owned()], - inputs: vec!["400:0:T:0101010101010101010101010101010101010101010101010101010101010101:0".to_owned()], - unlocks: vec![], - outputs: vec![ - "400:0:SIG(D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx)".to_owned(), - ], - comment: "".to_owned(), - signatures: vec![], - hash: Some("0202020202020202020202020202020202020202020202020202020202020202".to_owned()), - }], - inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), - signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), - hash: Some("0000000000000000000000000000000000000000000000000000000000000000".to_owned()), - ..Default::default() - })?; - - apply_block(&b3, &gva_db)?; - - revert_block(&b3, &gva_db)?; - - assert_eq!(gva_db.blockchain_time().count()?, 3); - assert_eq!(gva_db.blockchain_time().get(&U32BE(2))?, Some(5_247)); - assert_eq!(gva_db.balances().count()?, 2); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s1.clone()))?, - Some(SourceAmountValV2(SourceAmount::ZERO)) - ); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s2.clone()))?, - Some(SourceAmountValV2(SourceAmount::with_base0(1_000))) - ); - assert_eq!(gva_db.gva_utxos().count()?, 2); - assert_eq!( - gva_db - .gva_utxos() - .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, - vec![ - ( - GvaUtxoIdDbV1::new(s2.clone(), 1, Hash::default(), 0), - SourceAmountValV2(SourceAmount::with_base0(600)) - ), - ( - GvaUtxoIdDbV1::new(s2.clone(), 2, Hash([1u8; 32]), 0), - SourceAmountValV2(SourceAmount::with_base0(400)) - ), - ] - ); - - revert_block(&b2, &gva_db)?; - - assert_eq!(gva_db.blockchain_time().count()?, 2); - assert_eq!(gva_db.blockchain_time().get(&U32BE(1))?, Some(5_245)); - assert_eq!(gva_db.balances().count()?, 2); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s2.clone()))?, - Some(SourceAmountValV2(SourceAmount::with_base0(600))) - ); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s1.clone()))?, - Some(SourceAmountValV2(SourceAmount::with_base0(400))) - ); - assert_eq!(gva_db.gva_utxos().count()?, 2); - assert_eq!( - gva_db - .gva_utxos() - .iter(.., |it| it.collect::<KvResult<Vec<_>>>())?, - vec![ - ( - GvaUtxoIdDbV1::new(s1.clone(), 1, Hash::default(), 1), - SourceAmountValV2(SourceAmount::with_base0(400)) - ), - ( - GvaUtxoIdDbV1::new(s2.clone(), 1, Hash::default(), 0), - SourceAmountValV2(SourceAmount::with_base0(600)) - ), - ] - ); - - revert_block(&b1, &gva_db)?; - - assert_eq!(gva_db.blockchain_time().count()?, 1); - assert_eq!(gva_db.blockchain_time().get(&U32BE(0))?, Some(5_243)); - assert_eq!(gva_db.balances().count()?, 1); - assert_eq!( - gva_db.balances().get(&WalletConditionsV2(s1))?, - Some(SourceAmountValV2(SourceAmount::with_base0(1000))) - ); - assert_eq!(gva_db.balances().get(&WalletConditionsV2(s2))?, None); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/indexer/src/tx.rs b/rust-libs/modules/gva/indexer/src/tx.rs deleted file mode 100644 index 709ebd557..000000000 --- a/rust-libs/modules/gva/indexer/src/tx.rs +++ /dev/null @@ -1,514 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub(crate) type ScriptsHash = HashMap<WalletScriptV10, Hash>; - -fn get_script_hash(script: &WalletScriptV10, scripts_hash: &mut ScriptsHash) -> Hash { - if let Some(script_hash) = scripts_hash.get(script) { - *script_hash - } else { - let script_hash = Hash::compute(script.to_string().as_bytes()); - scripts_hash.insert(script.clone(), script_hash); - script_hash - } -} - -#[allow(clippy::too_many_arguments)] -pub(crate) fn apply_tx<B: Backend>( - current_blockstamp: Blockstamp, - current_time: i64, - gva_db: &mut GvaV1DbTxRw<B::Col>, - scripts_hash: &mut ScriptsHash, - tx_hash: Hash, - tx: &TransactionDocumentV10, - txs_by_issuer_mem: &mut HashMap<WalletHashWithBnV1Db, BTreeSet<Hash>>, - txs_by_recipient_mem: &mut HashMap<WalletHashWithBnV1Db, BTreeSet<Hash>>, -) -> KvResult<()> { - let mut issuers_scripts_hashs = BTreeSet::new(); - for input in tx.get_inputs() { - let (account_script_hash, account_script) = match input.id { - SourceIdV10::Utxo(utxo_id) => { - // Get issuer script & written block - let db_tx_origin = gva_db - .txs - .get(&HashKeyV2::from_ref(&utxo_id.tx_hash))? - .ok_or_else(|| { - KvError::DbCorrupted(format!("Not found origin tx of uxto {}", utxo_id)) - })?; - let utxo_script = db_tx_origin.tx.get_outputs()[utxo_id.output_index] - .conditions - .script - .clone(); - let utxo_script_hash = get_script_hash(&utxo_script, scripts_hash); - - // Remove consumed UTXOs - super::utxos::remove_utxo_v10::<B>( - &mut gva_db.scripts_by_pubkey, - &mut gva_db.gva_utxos, - utxo_id, - &utxo_script, - utxo_script_hash, - db_tx_origin.written_block.number.0, - )?; - - // Return utxo_script with hash - (utxo_script_hash, utxo_script) - } - SourceIdV10::Ud(UdSourceIdV10 { issuer, .. }) => { - let script = WalletScriptV10::single_sig(issuer); - (Hash::compute(script.to_string().as_bytes()), script) - } - }; - issuers_scripts_hashs.insert(account_script_hash); - // Insert on col `txs_by_issuer` - txs_by_issuer_mem - .entry(WalletHashWithBnV1Db::new( - account_script_hash, - current_blockstamp.number, - )) - .or_default() - .insert(tx_hash); - // Decrease account balance - decrease_account_balance::<B>( - account_script, - account_script_hash, - &mut gva_db.balances, - input.amount, - &mut gva_db.gva_identities, - false, - &mut gva_db.txs_by_recipient, - )?; - } - - for (output_index, output) in tx.get_outputs().iter().enumerate() { - let utxo_script_hash = get_script_hash(&output.conditions.script, scripts_hash); - // Insert created UTXOs - super::utxos::write_utxo_v10::<B>( - &mut gva_db.scripts_by_pubkey, - &mut gva_db.gva_utxos, - UtxoV10 { - id: UtxoIdV10 { - tx_hash, - output_index, - }, - amount: output.amount, - script: &output.conditions.script, - written_block: current_blockstamp.number, - }, - utxo_script_hash, - )?; - - // Insert on col `txs_by_recipient` - if !issuers_scripts_hashs.contains(&utxo_script_hash) { - txs_by_recipient_mem - .entry(WalletHashWithBnV1Db::new( - utxo_script_hash, - current_blockstamp.number, - )) - .or_default() - .insert(tx_hash); - } - - // Increase account balance - let balance = gva_db - .balances - .get(WalletConditionsV2::from_ref(&output.conditions.script))? - .unwrap_or_default(); - gva_db.balances.upsert( - WalletConditionsV2(output.conditions.script.clone()), - SourceAmountValV2(balance.0 + output.amount), - ); - } - - // Insert tx itself - gva_db.txs.upsert( - HashKeyV2(tx_hash), - GvaTxDbV1 { - tx: tx.clone(), - written_block: current_blockstamp, - written_time: current_time, - }, - ); - - Ok(()) -} - -pub(crate) fn revert_tx<B: Backend>( - block_number: BlockNumber, - gva_db: &mut GvaV1DbTxRw<B::Col>, - scripts_hash: &mut ScriptsHash, - tx_hash: &Hash, -) -> KvResult<Option<TransactionDocumentV10>> { - if let Some(tx_db) = gva_db.txs.get(&HashKeyV2::from_ref(tx_hash))? { - use dubp::documents::transaction::TransactionDocumentTrait as _; - for (output_index, output) in tx_db.tx.get_outputs().iter().enumerate() { - let script = &output.conditions.script; - let utxo_script_hash = get_script_hash(&script, scripts_hash); - - // Remove UTXOs created by this tx - super::utxos::remove_utxo_v10::<B>( - &mut gva_db.scripts_by_pubkey, - &mut gva_db.gva_utxos, - UtxoIdV10 { - tx_hash: *tx_hash, - output_index, - }, - script, - utxo_script_hash, - block_number.0, - )?; - - // Remove on col `txs_by_recipient` - let k = WalletHashWithBnV1Db::new(utxo_script_hash, block_number); - gva_db.txs_by_recipient.remove(k); - - // Decrease account balance - decrease_account_balance::<B>( - script.clone(), - utxo_script_hash, - &mut gva_db.balances, - output.amount, - &mut gva_db.gva_identities, - true, - &mut gva_db.txs_by_recipient, - )?; - } - // Recreate UTXOs consumed by this tx (and update balance) - for input in tx_db.tx.get_inputs() { - let (account_script_hash, account_script) = match input.id { - SourceIdV10::Utxo(utxo_id) => { - let db_tx_origin = gva_db - .txs - .get(&HashKeyV2::from_ref(&utxo_id.tx_hash))? - .ok_or_else(|| { - KvError::DbCorrupted(format!("Not found origin tx of uxto {}", utxo_id)) - })?; - let utxo_script = db_tx_origin.tx.get_outputs()[utxo_id.output_index] - .conditions - .script - .clone(); - let utxo_script_hash = get_script_hash(&utxo_script, scripts_hash); - super::utxos::write_utxo_v10::<B>( - &mut gva_db.scripts_by_pubkey, - &mut gva_db.gva_utxos, - UtxoV10 { - id: utxo_id, - amount: input.amount, - script: &utxo_script, - written_block: db_tx_origin.written_block.number, - }, - utxo_script_hash, - )?; - - // Return utxo_script - (utxo_script_hash, utxo_script) - } - SourceIdV10::Ud(UdSourceIdV10 { issuer, .. }) => { - let script = WalletScriptV10::single_sig(issuer); - (Hash::compute(script.to_string().as_bytes()), script) - } - }; - // Remove on col `txs_by_issuer` - gva_db - .txs_by_issuer - .remove(WalletHashWithBnV1Db::new(account_script_hash, block_number)); - // Increase account balance - let balance = gva_db - .balances - .get(WalletConditionsV2::from_ref(&account_script))? - .unwrap_or_default(); - - gva_db.balances.upsert( - WalletConditionsV2(account_script), - SourceAmountValV2(balance.0 + input.amount), - ); - } - - // Remove tx itself - gva_db.txs.remove(HashKeyV2(*tx_hash)); - - Ok(Some(tx_db.tx)) - } else { - Ok(None) - } -} - -fn decrease_account_balance<B: Backend>( - account_script: WalletScriptV10, - account_script_hash: Hash, - balances: &mut TxColRw<B::Col, BalancesEvent>, - decrease_amount: SourceAmount, - identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>, - revert: bool, - txs_by_recipients: &mut TxColRw<B::Col, TxsByRecipientEvent>, -) -> KvResult<()> { - if let Some(SourceAmountValV2(balance)) = - balances.get(WalletConditionsV2::from_ref(&account_script))? - { - let new_balance = balance - decrease_amount; - let remove_balance = if revert && new_balance == SourceAmount::ZERO { - let (k_min, k_max) = WalletHashWithBnV1Db::wallet_hash_interval(account_script_hash); - if txs_by_recipients - .iter(k_min..k_max, |it| it.keys().next_res())? - .is_some() - { - false - } else if let Some(pubkey) = account_script.as_single_sig() { - if let Some(idty) = identities.get(&PubKeyKeyV2(pubkey))? { - idty.first_ud.is_none() - } else { - true - } - } else { - true - } - } else { - false - }; - if remove_balance { - balances.remove(WalletConditionsV2(account_script)); - } else { - balances.upsert( - WalletConditionsV2(account_script), - SourceAmountValV2(new_balance), - ); - } - } - Ok(()) -} - -#[cfg(test)] -mod tests { - - use super::*; - use dubp::{ - crypto::keys::ed25519::Ed25519KeyPair, crypto::keys::KeyPair as _, - documents::smallvec::smallvec as svec, documents::transaction::v10::*, - documents::transaction::UTXOConditions, - }; - use duniter_dbs::BlockMetaV2; - use maplit::btreeset; - - #[test] - fn test_apply_tx() -> KvResult<()> { - let kp = Ed25519KeyPair::generate_random().expect("gen rand kp"); - let kp2 = Ed25519KeyPair::generate_random().expect("gen rand kp"); - - let ud0_amount = SourceAmount::with_base0(1000); - let o1_amount = ud0_amount - SourceAmount::with_base0(600); - let o2_amount = ud0_amount - SourceAmount::with_base0(400); - - let gva_db = GvaV1Db::<Mem>::open(MemConf::default())?; - - let b0 = BlockMetaV2 { - dividend: Some(ud0_amount), - ..Default::default() - }; - let current_blockstamp = b0.blockstamp(); - let pk = kp.public_key(); - //println!("TMP pk1={}", pk); - let pk2 = kp2.public_key(); - //println!("TMP pk2={}", pk2); - let script = WalletScriptV10::single_sig(pk); - let script2 = WalletScriptV10::single_sig(pk2); - let script_hash = Hash::compute(script.to_string().as_bytes()); - let script2_hash = Hash::compute(script2.to_string().as_bytes()); - - gva_db.balances_write().upsert( - WalletConditionsV2(script.clone()), - SourceAmountValV2(ud0_amount), - )?; - - let tx1 = TransactionDocumentV10Builder { - currency: "test", - blockstamp: current_blockstamp, - locktime: 0, - issuers: svec![pk], - inputs: &[TransactionInputV10 { - amount: ud0_amount, - id: SourceIdV10::Ud(UdSourceIdV10 { - issuer: pk, - block_number: BlockNumber(0), - }), - }], - unlocks: &[TransactionInputUnlocksV10::default()], - outputs: svec![ - TransactionOutputV10 { - amount: o1_amount, - conditions: UTXOConditions::from(script2.clone()), - }, - TransactionOutputV10 { - amount: o2_amount, - conditions: UTXOConditions::from(script.clone()), - } - ], - comment: "", - hash: None, - } - .build_and_sign(vec![kp.generate_signator()]); - let tx1_hash = tx1.get_hash(); - - let mut scripts_hash = HashMap::new(); - - let mut txs_by_issuer_mem = HashMap::new(); - let mut txs_by_recipient_mem = HashMap::new(); - (&gva_db).write(|mut db| { - apply_tx::<Mem>( - current_blockstamp, - b0.median_time as i64, - &mut db, - &mut scripts_hash, - tx1_hash, - &tx1, - &mut txs_by_issuer_mem, - &mut txs_by_recipient_mem, - ) - })?; - - assert_eq!(txs_by_issuer_mem.len(), 1); - assert_eq!( - txs_by_issuer_mem.get(&WalletHashWithBnV1Db::new(script_hash, BlockNumber(0))), - Some(&btreeset![tx1_hash]) - ); - assert_eq!(txs_by_recipient_mem.len(), 1); - assert_eq!( - txs_by_recipient_mem.get(&WalletHashWithBnV1Db::new(script2_hash, BlockNumber(0))), - Some(&btreeset![tx1_hash]) - ); - - assert_eq!( - gva_db - .balances() - .get(WalletConditionsV2::from_ref(&script2))?, - Some(SourceAmountValV2(o1_amount)) - ); - assert_eq!( - gva_db - .balances() - .get(WalletConditionsV2::from_ref(&script))?, - Some(SourceAmountValV2(o2_amount)) - ); - - let tx2 = TransactionDocumentV10Builder { - currency: "test", - blockstamp: current_blockstamp, - locktime: 0, - issuers: svec![pk2], - inputs: &[TransactionInputV10 { - amount: o1_amount, - id: SourceIdV10::Utxo(UtxoIdV10 { - tx_hash: tx1_hash, - output_index: 0, - }), - }], - unlocks: &[TransactionInputUnlocksV10::default()], - outputs: svec![TransactionOutputV10 { - amount: o1_amount, - conditions: UTXOConditions::from(script.clone()), - },], - comment: "", - hash: None, - } - .build_and_sign(vec![kp.generate_signator()]); - let tx2_hash = tx2.get_hash(); - - let mut txs_by_issuer_mem = HashMap::new(); - let mut txs_by_recipient_mem = HashMap::new(); - (&gva_db).write(|mut db| { - apply_tx::<Mem>( - current_blockstamp, - b0.median_time as i64, - &mut db, - &mut scripts_hash, - tx2_hash, - &tx2, - &mut txs_by_issuer_mem, - &mut txs_by_recipient_mem, - ) - })?; - - assert_eq!(txs_by_issuer_mem.len(), 1); - assert_eq!( - txs_by_issuer_mem.get(&WalletHashWithBnV1Db::new(script2_hash, BlockNumber(0))), - Some(&btreeset![tx2_hash]) - ); - assert_eq!(txs_by_recipient_mem.len(), 1); - assert_eq!( - txs_by_recipient_mem.get(&WalletHashWithBnV1Db::new(script_hash, BlockNumber(0))), - Some(&btreeset![tx2_hash]) - ); - - assert_eq!( - gva_db - .balances() - .get(WalletConditionsV2::from_ref(&script2))?, - Some(SourceAmountValV2(SourceAmount::ZERO)) - ); - assert_eq!( - gva_db - .balances() - .get(WalletConditionsV2::from_ref(&script))?, - Some(SourceAmountValV2(ud0_amount)) - ); - - (&gva_db).write(|mut db| { - revert_tx::<Mem>( - current_blockstamp.number, - &mut db, - &mut scripts_hash, - &tx2_hash, - ) - })?; - - assert_eq!( - gva_db - .balances() - .get(WalletConditionsV2::from_ref(&script2))?, - Some(SourceAmountValV2(o1_amount)) - ); - assert_eq!( - gva_db - .balances() - .get(WalletConditionsV2::from_ref(&script))?, - Some(SourceAmountValV2(o2_amount)) - ); - - (&gva_db).write(|mut db| { - revert_tx::<Mem>( - current_blockstamp.number, - &mut db, - &mut scripts_hash, - &tx1_hash, - ) - })?; - - assert_eq!( - gva_db - .balances() - .get(WalletConditionsV2::from_ref(&script2))?, - None - ); - assert_eq!( - gva_db - .balances() - .get(WalletConditionsV2::from_ref(&script))?, - Some(SourceAmountValV2(ud0_amount)) - ); - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/indexer/src/utxos.rs b/rust-libs/modules/gva/indexer/src/utxos.rs deleted file mode 100644 index 91ec82723..000000000 --- a/rust-libs/modules/gva/indexer/src/utxos.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -pub(crate) fn write_utxo_v10<'s, B: Backend>( - scripts_by_pubkey: &mut TxColRw<B::Col, ScriptsByPubkeyEvent>, - gva_utxos: &mut TxColRw<B::Col, GvaUtxosEvent>, - utxo: UtxoV10<'s>, - utxo_script_hash: Hash, -) -> KvResult<()> { - for pubkey in utxo.script.pubkeys() { - let mut pubkey_scripts = scripts_by_pubkey - .get(&PubKeyKeyV2(pubkey))? - .unwrap_or_default(); - if !pubkey_scripts.0.contains(&utxo.script) { - pubkey_scripts.0.insert(utxo.script.clone()); - scripts_by_pubkey.upsert(PubKeyKeyV2(pubkey), pubkey_scripts); - } - } - - let block_number = utxo.written_block.0; - let utxo_amount = utxo.amount; - let utxo_id = utxo.id; - gva_utxos.upsert( - GvaUtxoIdDbV1::new_( - utxo_script_hash, - block_number, - utxo_id.tx_hash, - utxo_id.output_index as u8, - ), - SourceAmountValV2(utxo_amount), - ); - - Ok(()) -} - -pub(crate) fn remove_utxo_v10<B: Backend>( - scripts_by_pubkey: &mut TxColRw<B::Col, ScriptsByPubkeyEvent>, - gva_utxos: &mut TxColRw<B::Col, GvaUtxosEvent>, - utxo_id: UtxoIdV10, - utxo_script: &WalletScriptV10, - utxo_script_hash: Hash, - written_block_number: u32, -) -> KvResult<()> { - gva_utxos.remove(GvaUtxoIdDbV1::new_( - utxo_script_hash, - written_block_number, - utxo_id.tx_hash, - utxo_id.output_index as u8, - )); - - let (k_min, k_max) = GvaUtxoIdDbV1::script_interval(utxo_script_hash); - if gva_utxos - .iter(k_min..k_max, |it| it.keys().next_res())? - .is_none() - { - let pubkeys = utxo_script.pubkeys(); - for pubkey in pubkeys { - let mut pubkey_scripts = - scripts_by_pubkey - .get(&PubKeyKeyV2(pubkey))? - .ok_or_else(|| { - KvError::DbCorrupted(format!( - "GVA: key {} dont exist on col `scripts_by_pubkey`.", - pubkey, - )) - })?; - pubkey_scripts.0.remove(utxo_script); - scripts_by_pubkey.upsert(PubKeyKeyV2(pubkey), pubkey_scripts); - } - } - Ok(()) -} diff --git a/rust-libs/modules/gva/src/anti_spam.rs b/rust-libs/modules/gva/src/anti_spam.rs deleted file mode 100644 index 30d2009ac..000000000 --- a/rust-libs/modules/gva/src/anti_spam.rs +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use async_mutex::Mutex; -use duniter_dbs::kv_typed::prelude::Arc; -use std::{ - collections::{HashMap, HashSet}, - net::IpAddr, - time::Duration, - time::Instant, -}; - -pub(super) const MAX_BATCH_SIZE: usize = 5; - -const COUNT_INTERVAL: usize = 10; -const MIN_DURATION_INTERVAL: Duration = Duration::from_secs(20); -const LARGE_DURATION_INTERVAL: Duration = Duration::from_secs(180); -const REDUCED_COUNT_INTERVAL: usize = COUNT_INTERVAL / 2; -const MAX_BAN_COUNT: usize = 16; -const BAN_FORGET_MIN_DURATION: Duration = Duration::from_secs(180); - -#[derive(Clone)] -pub(crate) struct AntiSpam { - state: Arc<Mutex<AntiSpamInner>>, - whitelist: HashSet<IpAddr>, -} - -#[derive(Clone)] -pub(crate) struct AntiSpamResponse { - pub is_whitelisted: bool, - pub is_ok: bool, -} - -impl AntiSpamResponse { - fn ban() -> Self { - AntiSpamResponse { - is_whitelisted: false, - is_ok: false, - } - } - fn ok() -> Self { - AntiSpamResponse { - is_whitelisted: false, - is_ok: true, - } - } - fn whitelisted() -> Self { - AntiSpamResponse { - is_whitelisted: true, - is_ok: true, - } - } -} - -struct AntiSpamInner { - ban: HashMap<IpAddr, (bool, usize, Instant)>, - ips_time: HashMap<IpAddr, (usize, Instant)>, -} - -impl From<&GvaConf> for AntiSpam { - fn from(conf: &GvaConf) -> Self { - AntiSpam { - state: Arc::new(Mutex::new(AntiSpamInner { - ban: HashMap::with_capacity(10), - ips_time: HashMap::with_capacity(10), - })), - whitelist: conf.get_whitelist().iter().copied().collect(), - } - } -} - -impl AntiSpam { - pub(crate) async fn verify( - &self, - remote_addr_opt: Option<std::net::IpAddr>, - ) -> AntiSpamResponse { - if let Some(ip) = remote_addr_opt { - log::trace!("GVA: receive request from {}", ip); - if self.whitelist.contains(&ip) { - AntiSpamResponse::whitelisted() - } else { - let mut guard = self.state.lock().await; - if let Some((is_banned, ban_count, instant)) = guard.ban.get(&ip).copied() { - let ban_duration = - Duration::from_secs(1 << std::cmp::min(ban_count, MAX_BAN_COUNT)); - if is_banned { - if Instant::now().duration_since(instant) > ban_duration { - guard.ban.insert(ip, (false, ban_count + 1, Instant::now())); - guard.ips_time.insert(ip, (1, Instant::now())); - AntiSpamResponse::ok() - } else { - guard.ban.insert(ip, (true, ban_count + 1, Instant::now())); - AntiSpamResponse::ban() - } - } else if Instant::now().duration_since(instant) - > std::cmp::max(ban_duration, BAN_FORGET_MIN_DURATION) - { - guard.ban.remove(&ip); - guard.ips_time.insert(ip, (1, Instant::now())); - AntiSpamResponse::ok() - } else { - Self::verify_interval(ip, &mut guard, ban_count) - } - } else { - Self::verify_interval(ip, &mut guard, 0) - } - } - } else { - AntiSpamResponse::ban() - } - } - fn verify_interval( - ip: IpAddr, - state: &mut AntiSpamInner, - ban_count: usize, - ) -> AntiSpamResponse { - if let Some((count, instant)) = state.ips_time.get(&ip).copied() { - if count == COUNT_INTERVAL { - let duration = Instant::now().duration_since(instant); - if duration > MIN_DURATION_INTERVAL { - if duration > LARGE_DURATION_INTERVAL { - state.ips_time.insert(ip, (1, Instant::now())); - AntiSpamResponse::ok() - } else { - state - .ips_time - .insert(ip, (REDUCED_COUNT_INTERVAL, Instant::now())); - AntiSpamResponse::ok() - } - } else { - state.ban.insert(ip, (true, ban_count, Instant::now())); - AntiSpamResponse::ban() - } - } else { - state.ips_time.insert(ip, (count + 1, instant)); - AntiSpamResponse::ok() - } - } else { - state.ips_time.insert(ip, (1, Instant::now())); - AntiSpamResponse::ok() - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::net::{Ipv4Addr, Ipv6Addr}; - - const LOCAL_IP4: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST); - const LOCAL_IP6: IpAddr = IpAddr::V6(Ipv6Addr::LOCALHOST); - - #[tokio::test] - async fn test_anti_spam() { - let anti_spam = AntiSpam::from(&GvaConf::default()); - assert!(!anti_spam.verify(None).await.is_ok); - - for _ in 0..(COUNT_INTERVAL * 2) { - assert!(anti_spam.verify(Some(LOCAL_IP4)).await.is_ok); - assert!(anti_spam.verify(Some(LOCAL_IP6)).await.is_ok); - } - - let extern_ip = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - - // Consume max queries - for _ in 0..COUNT_INTERVAL { - assert!(anti_spam.verify(Some(extern_ip)).await.is_ok); - } - // Should be banned - assert!(!anti_spam.verify(Some(extern_ip)).await.is_ok); - - // Should be un-banned after one second - tokio::time::sleep(Duration::from_millis(1_100)).await; - // Re-consume max queries - for _ in 0..COUNT_INTERVAL { - assert!(anti_spam.verify(Some(extern_ip)).await.is_ok); - } - // Should be banned for 2 seconds this time - tokio::time::sleep(Duration::from_millis(1_100)).await; - // Attempting a request when I'm banned must be twice my banning time - assert!(!anti_spam.verify(Some(extern_ip)).await.is_ok); - tokio::time::sleep(Duration::from_millis(4_100)).await; - // Re-consume max queries - for _ in 0..COUNT_INTERVAL { - assert!(anti_spam.verify(Some(extern_ip)).await.is_ok); - } - } -} diff --git a/rust-libs/modules/gva/src/lib.rs b/rust-libs/modules/gva/src/lib.rs deleted file mode 100644 index b637c342e..000000000 --- a/rust-libs/modules/gva/src/lib.rs +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces -)] - -mod anti_spam; -mod warp_; - -pub use duniter_conf::gva_conf::GvaConf; - -use async_graphql::http::GraphQLPlaygroundConfig; -use dubp::common::prelude::*; -use dubp::documents::transaction::TransactionDocumentV10; -use dubp::{block::DubpBlockV10, crypto::hashs::Hash}; -use dubp::{ - common::crypto::keys::{ed25519::PublicKey, KeyPair as _}, - crypto::keys::ed25519::Ed25519KeyPair, -}; -use duniter_conf::DuniterMode; -use duniter_dbs::databases::txs_mp_v2::TxsMpV2DbReadable; -use duniter_dbs::prelude::*; -use duniter_dbs::{kv_typed::prelude::*, FileBackend}; -use duniter_global::AsyncAccessor; -use duniter_gva_db::*; -use duniter_gva_gql::{GvaSchema, QueryContext}; -use duniter_gva_indexer::{get_gva_db_ro, get_gva_db_rw}; -use duniter_mempools::Mempools; -use futures::{StreamExt, TryStreamExt}; -use std::{convert::Infallible, path::Path}; -use warp::{http::Response as HttpResponse, Filter as _, Rejection}; - -#[derive(Debug)] -pub struct GvaModule { - conf: Option<GvaConf>, - currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - gva_db_ro: &'static GvaV1DbRo<FileBackend>, - mempools: Mempools, - mode: DuniterMode, - self_keypair: Ed25519KeyPair, - software_version: &'static str, -} - -#[async_trait::async_trait] -impl duniter_module::DuniterModule for GvaModule { - const INDEX_BLOCKS: bool = true; - - fn apply_block( - block: &DubpBlockV10, - _conf: &duniter_conf::DuniterConf, - profile_path_opt: Option<&Path>, - ) -> KvResult<()> { - let gva_db = get_gva_db_rw(profile_path_opt); - duniter_gva_indexer::apply_block(&block, gva_db) - } - fn revert_block( - block: &DubpBlockV10, - _conf: &duniter_conf::DuniterConf, - profile_path_opt: Option<&Path>, - ) -> KvResult<()> { - let gva_db = get_gva_db_rw(profile_path_opt); - duniter_gva_indexer::revert_block(&block, gva_db) - } - fn init( - conf: &duniter_conf::DuniterConf, - currency: &str, - dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - mempools: Mempools, - mode: duniter_conf::DuniterMode, - profile_path_opt: Option<&Path>, - software_version: &'static str, - ) -> anyhow::Result<(Self, Vec<duniter_module::Endpoint>)> { - let mut endpoints = Vec::new(); - if let Some(conf) = conf.gva.clone() { - let remote_port = conf.get_remote_port(); - endpoints.push(format!( - "GVA {}{} {} {}", - if remote_port == 443 || conf.get_remote_tls() { - "S " - } else { - "" - }, - conf.get_remote_host(), - remote_port, - conf.get_remote_path(), - )); - endpoints.push(format!( - "GVASUB {}{} {} {}", - if remote_port == 443 || conf.get_remote_tls() { - "S " - } else { - "" - }, - conf.get_remote_host(), - remote_port, - conf.get_remote_subscriptions_path(), - )); - }; - Ok(( - GvaModule { - conf: conf.gva.to_owned(), - currency: currency.to_owned(), - dbs_pool: dbs_pool.to_owned(), - gva_db_ro: get_gva_db_ro(profile_path_opt), - mempools, - mode, - self_keypair: conf.self_key_pair.clone(), - software_version, - }, - endpoints, - )) - } - - async fn start(self) -> anyhow::Result<()> { - // Do not start GVA server on js tests - if std::env::var_os("DUNITER_JS_TESTS") != Some("yes".into()) { - let GvaModule { - conf, - currency, - dbs_pool, - gva_db_ro, - mempools, - mode, - self_keypair, - software_version, - } = self; - - if let DuniterMode::Start = mode { - if let Some(conf) = conf { - GvaModule::start_inner( - conf, - currency, - dbs_pool, - gva_db_ro, - mempools, - self_keypair, - software_version, - ) - .await - } - } - } - Ok(()) - } - // Needed for BMA only, will be removed when the migration is complete. - fn get_transactions_history_for_bma( - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - profile_path_opt: Option<&Path>, - pubkey: PublicKey, - ) -> KvResult<Option<duniter_module::TxsHistoryForBma>> { - let gva_db = get_gva_db_ro(profile_path_opt); - let duniter_gva_dbs_reader::txs_history::TxsHistory { - sent, - received, - sending, - pending, - } = dbs_pool - .execute(move |dbs| { - duniter_gva_dbs_reader::txs_history::get_transactions_history_for_bma( - gva_db, - &dbs.txs_mp_db, - pubkey, - ) - }) - .expect("dbs pool disconnected")?; - Ok(Some(duniter_module::TxsHistoryForBma { - sent: sent - .into_iter() - .map( - |GvaTxDbV1 { - tx, - written_block, - written_time, - }| (tx, written_block, written_time), - ) - .collect(), - received: received - .into_iter() - .map( - |GvaTxDbV1 { - tx, - written_block, - written_time, - }| (tx, written_block, written_time), - ) - .collect(), - sending, - pending, - })) - } - // Needed for BMA only, will be removed when the migration is complete. - fn get_tx_by_hash( - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<SharedDbs<FileBackend>>, - hash: Hash, - profile_path_opt: Option<&Path>, - ) -> KvResult<Option<(TransactionDocumentV10, Option<BlockNumber>)>> { - let gva_db = get_gva_db_ro(profile_path_opt); - dbs_pool - .execute(move |dbs| { - if let Some(tx) = dbs.txs_mp_db.txs().get(&duniter_dbs::HashKeyV2(hash))? { - Ok(Some((tx.0, None))) - } else if let Some(tx_db) = gva_db.txs().get(&duniter_dbs::HashKeyV2(hash))? { - Ok(Some((tx_db.tx, Some(tx_db.written_block.number)))) - } else { - Ok(None) - } - }) - .expect("dbs pool disconnected") - } -} - -impl GvaModule { - async fn start_inner( - conf: GvaConf, - currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>, - gva_db_ro: &'static GvaV1DbRo<FileBackend>, - mempools: Mempools, - self_keypair: Ed25519KeyPair, - software_version: &'static str, - ) { - log::info!("GvaServer::start: conf={:?}", conf); - - // Create BcaExecutor and GvaSchema - let self_pubkey = self_keypair.public_key(); - duniter_bca::set_bca_executor( - currency.clone(), - AsyncAccessor::new(), - dbs_pool.clone(), - duniter_gva_dbs_reader::create_dbs_reader(gva_db_ro), - self_keypair, - software_version, - mempools.txs, - ); - let gva_schema = duniter_gva_gql::build_schema_with_data( - duniter_gva_gql::GvaSchemaData { - cm_accessor: AsyncAccessor::new(), - dbs_reader: duniter_gva_dbs_reader::create_dbs_reader(gva_db_ro), - dbs_pool, - server_meta_data: duniter_gva_gql::ServerMetaData { - currency, - self_pubkey, - software_version, - }, - txs_mempool: mempools.txs, - }, - true, - ); - - // Create warp server routes - let graphql_post = warp_::graphql( - &conf, - gva_schema.clone(), - async_graphql::http::MultipartOptions::default(), - ); - - let conf_clone = conf.clone(); - let graphql_playground = - warp::path::path(conf.get_path()) - .and(warp::get()) - .map(move || { - HttpResponse::builder() - .header("content-type", "text/html") - .body(async_graphql::http::playground_source( - GraphQLPlaygroundConfig::new(&format!("/{}", &conf_clone.get_path())) - .subscription_endpoint(&format!( - "/{}", - &conf_clone.get_subscriptions_path(), - )), - )) - }); - - let routes = graphql_playground - .or(graphql_post) - .or(warp_::graphql_ws(&conf, gva_schema.clone())) - .recover(|err: Rejection| async move { - if let Some(warp_::BadRequest(err)) = err.find() { - return Ok::<_, Infallible>(warp::reply::with_status( - err.to_string(), - http::StatusCode::BAD_REQUEST, - )); - } - - Ok(warp::reply::with_status( - "INTERNAL_SERVER_ERROR".to_string(), - http::StatusCode::INTERNAL_SERVER_ERROR, - )) - }); - - // Start warp server - log::info!( - "GVA server listen on http://{}:{}/{}", - conf.get_ip4(), - conf.get_port(), - &conf.get_path() - ); - if let Some(ip6) = conf.get_ip6() { - log::info!( - "GVA server listen on http://{}:{}/{}", - ip6, - conf.get_port(), - &conf.get_path() - ); - futures::future::join( - warp::serve(routes.clone()).run((conf.get_ip4(), conf.get_port())), - warp::serve(routes).run((ip6, conf.get_port())), - ) - .await; - } else { - warp::serve(routes) - .run((conf.get_ip4(), conf.get_port())) - .await; - } - log::warn!("GVA server stopped"); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use duniter_conf::DuniterConf; - use duniter_mempools::Mempools; - use duniter_module::DuniterModule; - use fast_threadpool::{ThreadPool, ThreadPoolConfig}; - use unwrap::unwrap; - - #[tokio::test] - #[ignore] - async fn launch_mem_gva() -> anyhow::Result<()> { - let dbs = unwrap!(SharedDbs::mem()); - let threadpool = ThreadPool::start(ThreadPoolConfig::default(), dbs); - - GvaModule::init( - &DuniterConf::default(), - "", - &threadpool.into_async_handler(), - Mempools::default(), - duniter_conf::DuniterMode::Start, - None, - "test", - )? - .0 - .start() - .await?; - - Ok(()) - } -} diff --git a/rust-libs/modules/gva/src/warp_.rs b/rust-libs/modules/gva/src/warp_.rs deleted file mode 100644 index 2673a34fc..000000000 --- a/rust-libs/modules/gva/src/warp_.rs +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use std::{ - net::{IpAddr, SocketAddr}, - time::Duration, -}; - -use bytes::Bytes; - -use crate::anti_spam::{AntiSpam, AntiSpamResponse}; -use crate::*; - -const MAX_BATCH_REQ_PROCESS_DURATION_IN_MILLIS: u64 = 5_000; - -pub struct BadRequest(pub anyhow::Error); - -impl std::fmt::Debug for BadRequest { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl warp::reject::Reject for BadRequest {} - -pub struct ReqExecTooLong; - -impl std::fmt::Debug for ReqExecTooLong { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "server error: request execution too long") - } -} - -impl warp::reject::Reject for ReqExecTooLong {} - -struct GraphQlRequest { - inner: async_graphql::BatchRequest, -} - -impl GraphQlRequest { - fn data<D: std::any::Any + Copy + Send + Sync>(self, data: D) -> Self { - match self.inner { - async_graphql::BatchRequest::Single(request) => { - Self::new(async_graphql::BatchRequest::Single(request.data(data))) - } - async_graphql::BatchRequest::Batch(requests) => { - Self::new(async_graphql::BatchRequest::Batch( - requests.into_iter().map(|req| req.data(data)).collect(), - )) - } - } - } - #[allow(clippy::from_iter_instead_of_collect)] - async fn execute(self, schema: GvaSchema) -> async_graphql::BatchResponse { - use std::iter::FromIterator as _; - match self.inner { - async_graphql::BatchRequest::Single(request) => { - async_graphql::BatchResponse::Single(schema.execute(request).await) - } - async_graphql::BatchRequest::Batch(requests) => async_graphql::BatchResponse::Batch( - futures::stream::FuturesOrdered::from_iter( - requests - .into_iter() - .zip(std::iter::repeat(schema)) - .map(|(request, schema)| async move { schema.execute(request).await }), - ) - .collect() - .await, - ), - } - } - fn len(&self) -> usize { - match &self.inner { - async_graphql::BatchRequest::Single(_) => 1, - async_graphql::BatchRequest::Batch(requests) => requests.len(), - } - } - fn new(inner: async_graphql::BatchRequest) -> Self { - Self { inner } - } - fn single(request: async_graphql::Request) -> Self { - Self::new(async_graphql::BatchRequest::Single(request)) - } -} - -enum ServerResponse { - Bincode(Vec<u8>), - GraphQl(async_graphql::BatchResponse), -} - -impl warp::reply::Reply for ServerResponse { - fn into_response(self) -> warp::reply::Response { - match self { - ServerResponse::Bincode(bytes) => bytes.into_response(), - ServerResponse::GraphQl(gql_batch_resp) => { - let mut resp = warp::reply::with_header( - warp::reply::json(&gql_batch_resp), - "content-type", - "application/json", - ) - .into_response(); - add_cache_control_batch(&mut resp, &gql_batch_resp); - resp - } - } - } -} - -fn add_cache_control_batch( - http_resp: &mut warp::reply::Response, - batch_resp: &async_graphql::BatchResponse, -) { - match batch_resp { - async_graphql::BatchResponse::Single(resp) => add_cache_control(http_resp, resp), - async_graphql::BatchResponse::Batch(resps) => { - for resp in resps { - add_cache_control(http_resp, resp) - } - } - } -} - -fn add_cache_control(http_resp: &mut warp::reply::Response, resp: &async_graphql::Response) { - if resp.is_ok() { - if let Some(cache_control) = resp.cache_control.value() { - if let Ok(value) = cache_control.parse() { - http_resp.headers_mut().insert("cache-control", value); - } - } - } -} - -pub(crate) fn graphql( - conf: &GvaConf, - gva_schema: GvaSchema, - opts: async_graphql::http::MultipartOptions, -) -> impl warp::Filter<Extract = (impl warp::Reply,), Error = Rejection> + Clone { - let anti_spam = AntiSpam::from(conf); - let opts = Arc::new(opts); - warp::path::path(conf.get_path()) - .and(warp::method()) - .and(warp::query::raw().or(warp::any().map(String::new)).unify()) - .and(warp::addr::remote()) - .and(warp::header::optional::<IpAddr>("X-Real-IP")) - .and(warp::header::optional::<String>("content-type")) - .and(warp::body::stream()) - .and(warp::any().map(move || anti_spam.clone())) - .and(warp::any().map(move || gva_schema.clone())) - .and(warp::any().map(move || opts.clone())) - .and_then( - |method, - query: String, - remote_addr: Option<SocketAddr>, - x_real_ip: Option<IpAddr>, - content_type: Option<String>, - body, - anti_spam: AntiSpam, - gva_schema: GvaSchema, - opts: Arc<async_graphql::http::MultipartOptions>| async move { - let AntiSpamResponse { - is_whitelisted, - is_ok, - } = anti_spam - .verify(x_real_ip.or_else(|| remote_addr.map(|ra| ra.ip()))) - .await; - if is_ok { - if method == http::Method::GET { - let request: async_graphql::Request = serde_urlencoded::from_str(&query) - .map_err(|err| warp::reject::custom(BadRequest(err.into())))?; - Ok(ServerResponse::GraphQl( - GraphQlRequest::single(request.data(QueryContext { is_whitelisted })) - .execute(gva_schema) - .await, - )) - } else { - let body_stream = futures::TryStreamExt::map_err(body, |err| { - std::io::Error::new(std::io::ErrorKind::Other, err) - }) - .map_ok(|mut buf| { - let remaining = warp::Buf::remaining(&buf); - warp::Buf::copy_to_bytes(&mut buf, remaining) - }); - if content_type.as_deref() == Some("application/bincode") { - tokio::time::timeout( - Duration::from_millis(MAX_BATCH_REQ_PROCESS_DURATION_IN_MILLIS), - process_bincode_batch_queries(body_stream, is_whitelisted), - ) - .await - .map_err(|_| warp::reject::custom(ReqExecTooLong))? - } else { - tokio::time::timeout( - Duration::from_millis(MAX_BATCH_REQ_PROCESS_DURATION_IN_MILLIS), - process_json_batch_queries( - body_stream.into_async_read(), - content_type, - gva_schema, - is_whitelisted, - *opts, - ), - ) - .await - .map_err(|_| warp::reject::custom(ReqExecTooLong))? - } - } - } else { - Err(warp::reject::custom(BadRequest(anyhow::Error::msg( - r#"{ "error": "too many requests" }"#, - )))) - } - }, - ) -} - -async fn process_bincode_batch_queries( - body_reader: impl 'static + futures::TryStream<Ok = Bytes, Error = std::io::Error> + Send + Unpin, - is_whitelisted: bool, -) -> Result<ServerResponse, warp::Rejection> { - Ok(ServerResponse::Bincode( - duniter_bca::execute(body_reader, is_whitelisted).await, - )) -} - -async fn process_json_batch_queries( - body_reader: impl 'static + futures::AsyncRead + Send + Unpin, - content_type: Option<String>, - gva_schema: GvaSchema, - is_whitelisted: bool, - opts: async_graphql::http::MultipartOptions, -) -> Result<ServerResponse, warp::Rejection> { - let batch_request = GraphQlRequest::new( - async_graphql::http::receive_batch_body( - content_type, - body_reader, - async_graphql::http::MultipartOptions::clone(&opts), - ) - .await - .map_err(|err| warp::reject::custom(BadRequest(err.into())))?, - ); - if is_whitelisted || batch_request.len() <= anti_spam::MAX_BATCH_SIZE { - Ok(ServerResponse::GraphQl( - batch_request - .data(QueryContext { is_whitelisted }) - .execute(gva_schema) - .await, - )) - } else { - Err(warp::reject::custom(BadRequest(anyhow::Error::msg( - r#"{ "error": "The batch contains too many requests" }"#, - )))) - } -} - -pub(crate) fn graphql_ws( - conf: &GvaConf, - schema: GvaSchema, -) -> impl warp::Filter<Extract = (impl warp::Reply,), Error = Rejection> + Clone { - let anti_spam = AntiSpam::from(conf); - warp::path::path(conf.get_subscriptions_path()) - .and(warp::addr::remote()) - .and(warp::header::optional::<IpAddr>("X-Real-IP")) - .and(warp::ws()) - .and(warp::any().map(move || schema.clone())) - .and(warp::any().map(move || anti_spam.clone())) - .and_then( - |remote_addr: Option<SocketAddr>, - x_real_ip: Option<IpAddr>, - ws: warp::ws::Ws, - schema: GvaSchema, - anti_spam: AntiSpam| async move { - let AntiSpamResponse { - is_whitelisted: _, - is_ok, - } = anti_spam - .verify(x_real_ip.or_else(|| remote_addr.map(|ra| ra.ip()))) - .await; - if is_ok { - Ok((ws, schema)) - } else { - Err(warp::reject::custom(BadRequest(anyhow::Error::msg( - r#"{ "error": "too many requests" }"#, - )))) - } - }, - ) - .and_then(|(ws, schema): (warp::ws::Ws, GvaSchema)| { - let reply = ws.on_upgrade(move |websocket| { - let (ws_sender, ws_receiver) = websocket.split(); - - async move { - let _ = async_graphql::http::WebSocket::new( - schema, - ws_receiver - .take_while(|msg| futures::future::ready(msg.is_ok())) - .map(Result::unwrap) - .map(warp::ws::Message::into_bytes), - async_graphql::http::WebSocketProtocols::SubscriptionsTransportWS, - ) - .map(warp::ws::Message::text) - .map(Ok) - .forward(ws_sender) - .await; - } - }); - - futures::future::ready(Ok::<_, Rejection>(warp::reply::with_header( - reply, - "Sec-WebSocket-Protocol", - "graphql-ws", - ))) - }) -} diff --git a/rust-libs/tests/duniter-integration-tests/Cargo.toml b/rust-libs/tests/duniter-integration-tests/Cargo.toml index 3f3bb65d2..e775f0c15 100644 --- a/rust-libs/tests/duniter-integration-tests/Cargo.toml +++ b/rust-libs/tests/duniter-integration-tests/Cargo.toml @@ -8,12 +8,7 @@ edition = "2018" [dependencies] anyhow = "1.0.34" dubp = { version = "0.51.0", features = ["duniter"] } -duniter-conf = { path = "../../duniter-conf" } -duniter-dbs = { path = "../../duniter-dbs" } -duniter-bc-reader = { path = "../../duniter-bc-reader" } -duniter-dbs-write-ops = { path = "../../duniter-dbs-write-ops" } -duniter-mempools = { path = "../../duniter-mempools" } -duniter-module = { path = "../../duniter-module" } +duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core", features = ["bc-writer"] } duniter-server = { path = "../../duniter-server", features = ["gva"] } fast-threadpool = "0.2.3" flume = "0.10.0" diff --git a/rust-libs/tools/kv_typed/Cargo.toml b/rust-libs/tools/kv_typed/Cargo.toml deleted file mode 100644 index 65554446b..000000000 --- a/rust-libs/tools/kv_typed/Cargo.toml +++ /dev/null @@ -1,59 +0,0 @@ -[package] -name = "kv_typed" -version = "0.1.0" -authors = ["elois <c@elo.tf>"] -description = "Strongly typed key-value storage" -repository = "https://git.duniter.org/nodes/typescript/duniter" -keywords = ["database", "key", "sled"] -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -byteorder = "1.3.4" -cfg-if = "0.1.10" -flume = "0.10.0" -leveldb_minimal = { version = "0.1.0", optional = true } -lmdb-zero = { version = "0.4.4", optional = true } -mockall = { version = "0.9.1", optional = true } -parking_lot = "0.11.0" -paste = "1.0.2" -rayon = { version = "1.3.1", optional = true } -regex = { version = "1.3.9", optional = true } -serde_json = { version = "1.0.53", optional = true } -sled = { version = "0.34.6", optional = true, features = ["compression"] } -smallvec = { version = "1.4.0", features = ["serde", "write"] } -thiserror = "1.0.20" -uninit = "0.4.0" -zerocopy = "0.3.0" - -[[bench]] -name = "compare_backends" -harness = false -required-features = ["leveldb_backend", "sled_backend"] - -[dev-dependencies] -async-std = { version = "1.6.3", features = ["attributes"] } -maybe-async = "0.2.0" -smallvec = { version = "1.4.0", features = ["serde", "write"] } -tempfile = "3.2.0" -unwrap = "1.2.1" - -# Benches dependencies -criterion = { version = "0.3.1" } - -[features] -#default = ["sled_backend"] - -async = [] -explorer = ["rayon", "regex", "serde_json"] -leveldb_backend = ["leveldb_minimal"] -lmdb_backend = ["lmdb-zero"] -sled_backend = ["sled"] - -#mock = ["mockall"] - -default = ["sled_backend", "explorer"] -#default = ["mock"] diff --git a/rust-libs/tools/kv_typed/benches/compare_backends.rs b/rust-libs/tools/kv_typed/benches/compare_backends.rs deleted file mode 100644 index d21049b49..000000000 --- a/rust-libs/tools/kv_typed/benches/compare_backends.rs +++ /dev/null @@ -1,146 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion, /*, AxisScale, PlotConfiguration*/}; -use kv_typed::prelude::*; -use std::{fmt::Debug, path::PathBuf}; - -kv_typed::db_schema!(Test, [["c1", Col1, u32, String],]); -//const LEVELDB_DIR_PATH: &str = "/dev/shm/kv_typed/benches/compare_backends/leveldb"; -//const LMDB_DIR_PATH: &str = "/dev/shm/kv_typed/benches/compare_backends/lmdb"; -const LEVELDB_DIR_PATH: &str = "/home/elois/tmp/kv_typed/benches/compare_backends/leveldb"; -const LMDB_DIR_PATH: &str = "/home/elois/tmp/kv_typed/benches/compare_backends/lmdb"; -const SLED_DIR_PATH: &str = "/home/elois/tmp/kv_typed/benches/compare_backends/sled"; -static SMALL_VAL: &str = "abcdefghijklmnopqrst"; -static LARGE_VAL: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -fn read_n_entries<B: Backend>(db: &TestDb<B>, n: u32, val: String) { - for i in 0..n { - assert_eq!(db.col1().get(&i).expect("db err"), Some(val.clone())); - } - /*db.col1().iter(.., |iter| { - let mut iter = iter.values(); - for _ in 0..n { - assert_eq!(iter.next_res().expect(""), Some(val.clone())); - //assert_eq!(db.col1().get(&i).expect(""), Some(val.clone())); - } - assert_eq!(iter.next_res().expect(""), None); - });*/ -} -fn remove_and_write_n_entries<B: Backend>(db: &TestDb<B>, n: u32, val: String) { - for i in 0..n { - db.col1_write().remove(i).expect("fail to write"); - db.col1_write() - .upsert(i, val.clone()) - .expect("fail to write"); - } -} -fn write_n_entries<B: Backend>(db: &TestDb<B>, n: u32, val: String) { - for i in 0..n { - db.col1_write() - .upsert(i, val.clone()) - .expect("fail to write"); - } -} - -pub fn benchmark(c: &mut Criterion) { - // Read chart config - //let read_chart_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - - // Create DBs - std::fs::create_dir_all(LEVELDB_DIR_PATH).expect("fail to create leveldb dir"); - let leveldb_db = TestDb::<LevelDb>::open(LevelDbConf { - db_path: PathBuf::from(LEVELDB_DIR_PATH), - ..Default::default() - }) - .expect("fail to open db"); - /*let lmdb_db = - TestDb::<Lmdb>::open(LmdbConf::default().folder_path(PathBuf::from(LMDB_DIR_PATH))) - .expect("fail to open db");*/ - //let mem_db = TestDb::<Mem>::open(MemConf::default()).expect("fail to open db"); - let sled_db = - TestDb::<Sled>::open(SledConf::default().path(SLED_DIR_PATH)).expect("fail to open db"); - - // Test write small values - let mut group = c.benchmark_group("write small values"); - /*group.bench_function("lmdb", |b| { - b.iter(|| remove_and_write_n_entries(&lmdb_db, 100, String::from(SMALL_VAL))) - });*/ - group.bench_function("leveldb", |b| { - b.iter(|| remove_and_write_n_entries(&leveldb_db, 100, String::from(SMALL_VAL))) - }); - /*group.bench_function("mem", |b| { - b.iter(|| remove_and_write_n_entries(&mem_db, 100, String::from(SMALL_VAL))) - });*/ - group.bench_function("sled", |b| { - b.iter(|| remove_and_write_n_entries(&sled_db, 100, String::from(SMALL_VAL))) - }); - group.finish(); - - // Prepare read test - //write_n_entries(&lmdb_db, 100, String::from(SMALL_VAL)); - write_n_entries(&leveldb_db, 100, String::from(SMALL_VAL)); - //write_n_entries(&mem_db, 100, String::from(SMALL_VAL)); - write_n_entries(&sled_db, 100, String::from(SMALL_VAL)); - - // Test read small values - let mut group = c.benchmark_group("read small values"); - //group.plot_config(read_chart_config.clone()); - /*group.bench_function("lmdb", |b| { - b.iter(|| read_n_entries(&lmdb_db, 100, String::from(SMALL_VAL))) - });*/ - group.bench_function("leveldb", |b| { - b.iter(|| read_n_entries(&leveldb_db, 100, String::from(SMALL_VAL))) - }); - /*group.bench_function("mem", |b| { - b.iter(|| read_n_entries(&mem_db, 100, String::from(SMALL_VAL))) - });*/ - group.bench_function("sled", |b| { - b.iter(|| read_n_entries(&sled_db, 100, String::from(SMALL_VAL))) - }); - group.finish(); - - // Test write large values - let mut group = c.benchmark_group("write large values"); - /*group.bench_function("lmdb", |b| { - b.iter(|| remove_and_write_n_entries(&lmdb_db, 100, String::from(LARGE_VAL))) - });*/ - group.bench_function("leveldb", |b| { - b.iter(|| remove_and_write_n_entries(&leveldb_db, 100, String::from(LARGE_VAL))) - }); - /*group.bench_function("mem", |b| { - b.iter(|| remove_and_write_n_entries(&mem_db, 100, String::from(LARGE_VAL))) - });*/ - group.bench_function("sled", |b| { - b.iter(|| remove_and_write_n_entries(&sled_db, 100, String::from(LARGE_VAL))) - }); - group.finish(); - - // Prepare read test - //write_n_entries(&lmdb_db, 100, String::from(LARGE_VAL)); - write_n_entries(&leveldb_db, 100, String::from(LARGE_VAL)); - //write_n_entries(&mem_db, 100, String::from(LARGE_VAL)); - write_n_entries(&sled_db, 100, String::from(LARGE_VAL)); - - // Test read large values - let mut group = c.benchmark_group("read large values"); - //group.plot_config(read_chart_config); - /*group.bench_function("lmdb", |b| { - b.iter(|| read_n_entries(&lmdb_db, 100, String::from(LARGE_VAL))) - });*/ - group.bench_function("leveldb", |b| { - b.iter(|| read_n_entries(&leveldb_db, 100, String::from(LARGE_VAL))) - }); - /*group.bench_function("mem", |b| { - b.iter(|| read_n_entries(&mem_db, 100, String::from(LARGE_VAL))) - });*/ - group.bench_function("sled", |b| { - b.iter(|| read_n_entries(&sled_db, 100, String::from(LARGE_VAL))) - }); - group.finish(); - - // Close DBs - std::fs::remove_dir_all(LEVELDB_DIR_PATH).expect("fail to remove leveldb dir"); - std::fs::remove_dir_all(LMDB_DIR_PATH).expect("fail to remove lmdb dir"); - std::fs::remove_dir_all(SLED_DIR_PATH).expect("fail to remove sled dir"); -} - -criterion_group!(benches, benchmark); -criterion_main!(benches); diff --git a/rust-libs/tools/kv_typed/src/as_bytes.rs b/rust-libs/tools/kv_typed/src/as_bytes.rs deleted file mode 100644 index 46e0e3f9f..000000000 --- a/rust-libs/tools/kv_typed/src/as_bytes.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::*; - -pub trait AsBytes { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, f: F) -> T; -} - -impl AsBytes for () { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(&[]) - } -} - -impl AsBytes for String { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(self.as_bytes()) - } -} - -impl<T> AsBytes for Vec<T> -where - T: zerocopy::AsBytes, -{ - fn as_bytes<D, F: FnMut(&[u8]) -> D>(&self, mut f: F) -> D { - use zerocopy::AsBytes as _; - f((&self[..]).as_bytes()) - } -} - -macro_rules! impl_as_bytes_for_smallvec { - ($($N:literal),*) => {$( - impl<T> AsBytes for SmallVec<[T; $N]> - where - T: zerocopy::AsBytes, - { - fn as_bytes<D, F: FnMut(&[u8]) -> D>(&self, mut f: F) -> D { - use zerocopy::AsBytes as _; - f((&self[..]).as_bytes()) - } - } - )*}; -} -impl_as_bytes_for_smallvec!(1, 2, 4, 8, 16, 32, 64); - -impl<T> AsBytes for BTreeSet<T> -where - T: zerocopy::AsBytes + Copy, -{ - fn as_bytes<D, F: FnMut(&[u8]) -> D>(&self, mut f: F) -> D { - use zerocopy::AsBytes as _; - f((&self.iter().copied().collect::<SmallVec<[T; 32]>>()[..]).as_bytes()) - } -} - -impl<T> AsBytes for HashSet<T> -where - T: zerocopy::AsBytes + Copy, -{ - fn as_bytes<D, F: FnMut(&[u8]) -> D>(&self, mut f: F) -> D { - use zerocopy::AsBytes as _; - f((&self.iter().copied().collect::<SmallVec<[T; 32]>>()[..]).as_bytes()) - } -} - -macro_rules! impl_as_bytes_for_le_numbers { - ($($T:ty),*) => {$( - impl AsBytes for $T { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(&self.to_le_bytes()[..]) - } - } - )*}; -} -impl_as_bytes_for_le_numbers!( - usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64 -); - -macro_rules! impl_as_bytes_for_be_numbers { - ($($T:ty),*) => {$( - impl AsBytes for $T { - fn as_bytes<T, F: FnMut(&[u8]) -> T>(&self, mut f: F) -> T { - f(&self.0.to_be_bytes()[..]) - } - } - )*}; -} -impl_as_bytes_for_be_numbers!(U32BE, U64BE); diff --git a/rust-libs/tools/kv_typed/src/backend.rs b/rust-libs/tools/kv_typed/src/backend.rs deleted file mode 100644 index 5e91cc21d..000000000 --- a/rust-libs/tools/kv_typed/src/backend.rs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed Backend Trait - -#[cfg(feature = "leveldb_backend")] -pub mod leveldb; -#[cfg(feature = "lmdb_backend")] -pub mod lmdb; -pub mod memory; -pub mod memory_singleton; -#[cfg(feature = "mock")] -pub mod mock; -#[cfg(feature = "sled_backend")] -pub mod sled; - -use crate::*; - -pub trait Backend: 'static + Clone + Sized { - const NAME: &'static str; - type Col: BackendCol; - type Conf: Default; - - fn open(conf: &Self::Conf) -> KvResult<Self>; - fn open_col(&mut self, conf: &Self::Conf, col_name: &str) -> KvResult<Self::Col>; -} - -pub trait BackendCol: 'static + Clone + Debug + Send + Sync { - type Batch: BackendBatch; - type KeyBytes: KeyBytes; - type ValueBytes: ValueBytes; - type Iter: BackendIter<Self::KeyBytes, Self::ValueBytes>; - - fn get<K: Key, V: Value>(&self, k: &K) -> KvResult<Option<V>>; - fn get_ref<K: Key, V: ValueZc, D, F: Fn(&V::Ref) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>>; - fn get_ref_slice<K: Key, V: ValueSliceZc, D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>>; - fn clear(&mut self) -> KvResult<()>; - fn contains_key<K: Key>(&self, k: &K) -> KvResult<bool>; - fn count(&self) -> KvResult<usize>; - fn iter<K: Key, V: Value>(&self, range: RangeBytes) -> Self::Iter; - fn iter_ref_slice<D, K, V, F>( - &self, - range: RangeBytes, - f: F, - ) -> KvInnerIterRefSlice<Self, D, K, V, F> - where - K: KeyZc, - V: ValueSliceZc, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, - { - KvInnerIterRefSlice { - backend_iter: self.iter::<K, V>(range), - f, - phantom: PhantomData, - } - } - fn put<K: Key, V: Value>(&mut self, k: &K, value: &V) -> KvResult<()>; - fn delete<K: Key>(&mut self, k: &K) -> KvResult<()>; - fn new_batch() -> Self::Batch; - fn write_batch(&mut self, inner_batch: Self::Batch) -> KvResult<()>; - fn save(&self) -> KvResult<()>; -} - -pub trait BackendIter<K: KeyBytes, V: ValueBytes>: - Iterator<Item = Result<(K, V), DynErr>> + ReversableIterator -{ -} - -#[cfg_attr(feature = "mock", mockall::automock)] -pub trait BackendBatch: Debug + Default { - fn upsert(&mut self, k: &[u8], v: &[u8]); - fn remove(&mut self, k: &[u8]); -} - -#[cfg(feature = "mock")] -impl Debug for MockBackendBatch { - fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - unimplemented!() - } -} diff --git a/rust-libs/tools/kv_typed/src/backend/leveldb.rs b/rust-libs/tools/kv_typed/src/backend/leveldb.rs deleted file mode 100644 index 1ecd676c8..000000000 --- a/rust-libs/tools/kv_typed/src/backend/leveldb.rs +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! LevelDb backend for KV Typed - -use crate::*; -pub use leveldb_minimal::database::batch::{Batch as _, Writebatch as WriteBatch}; -use leveldb_minimal::database::cache::Cache as LevelDbCache; -pub use leveldb_minimal::database::error::Error as LevelDbError; -use leveldb_minimal::database::iterator::Iterator as LevelDbIterator; -pub use leveldb_minimal::database::Database as LevelDbDb; -use leveldb_minimal::iterator::{Iterable, LevelDBIterator as _}; -use leveldb_minimal::kv::KV as _; -pub use leveldb_minimal::options::{Options as LevelDbOptions, ReadOptions, WriteOptions}; -use leveldb_minimal::Compression; -use std::path::PathBuf; - -#[derive(Clone, Copy, Debug)] -pub struct LevelDb; - -impl Backend for LevelDb { - const NAME: &'static str = "leveldb"; - type Col = LevelDbCol; - type Conf = LevelDbConf; - - fn open(_conf: &Self::Conf) -> KvResult<Self> { - Ok(LevelDb) - } - fn open_col(&mut self, conf: &Self::Conf, col_name: &str) -> KvResult<Self::Col> { - Ok(LevelDbCol(Arc::new(LevelDbDb::open( - &conf.db_path.join(col_name), - conf.clone().into(), - )?))) - } -} - -#[derive(Clone)] -pub struct LevelDbCol(Arc<LevelDbDb>); - -impl Debug for LevelDbCol { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("LevelDbCol") - .field("0", &"Arc<LevelDbDb>") - .finish() - } -} - -#[derive(Default)] -pub struct LevelDbBatch(WriteBatch); - -impl Debug for LevelDbBatch { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("LevelDbBatch") - .field("0", &"WriteBatch") - .finish() - } -} - -impl BackendBatch for LevelDbBatch { - fn upsert(&mut self, k: &[u8], v: &[u8]) { - self.0.put(k, v) - } - - fn remove(&mut self, k: &[u8]) { - self.0.delete(k) - } -} - -#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] -pub struct LevelDbBytes(Vec<u8>); -impl AsRef<[u8]> for LevelDbBytes { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} -impl FromBytes for LevelDbBytes { - type Err = std::convert::Infallible; - - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> { - Ok(Self(bytes.into())) - } -} - -impl BackendCol for LevelDbCol { - type Batch = LevelDbBatch; - type KeyBytes = LevelDbBytes; - type ValueBytes = LevelDbBytes; - type Iter = LevelDbIter; - - #[inline(always)] - fn new_batch() -> Self::Batch { - LevelDbBatch(WriteBatch::default()) - } - fn clear(&mut self) -> KvResult<()> { - let keys = self - .0 - .iter(ReadOptions::new()) - .map(|(k, _v)| k) - .collect::<Vec<Vec<u8>>>(); - for key in keys { - self.0.delete(WriteOptions::new(), key.as_ref())?; - } - Ok(()) - } - #[inline(always)] - fn count(&self) -> KvResult<usize> { - Ok(self - .0 - .iter(ReadOptions { - verify_checksums: false, - fill_cache: false, - snapshot: None, - }) - .count()) - } - #[inline(always)] - fn contains_key<K: Key>(&self, k: &K) -> KvResult<bool> { - k.as_bytes(|k_bytes| Ok(self.0.get(ReadOptions::new(), k_bytes)?.is_some())) - } - #[inline(always)] - fn get<K: Key, V: Value>(&self, k: &K) -> KvResult<Option<V>> { - k.as_bytes(|k_bytes| { - self.0 - .get(ReadOptions::new(), k_bytes)? - .map(|bytes| V::from_bytes(&bytes).map_err(|e| KvError::DeserError(e.into()))) - .transpose() - }) - } - #[inline(always)] - fn get_ref<K: Key, V: ValueZc, D, F: Fn(&V::Ref) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>> { - k.as_bytes(|k_bytes| { - self.0 - .get(ReadOptions::new(), k_bytes)? - .map(|bytes| { - if let Some(layout_verified) = - zerocopy::LayoutVerified::<_, V::Ref>::new(bytes.as_ref()) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - )) - } - }) - .transpose() - }) - } - #[inline(always)] - fn get_ref_slice<K: Key, V: ValueSliceZc, D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>> { - k.as_bytes(|k_bytes| { - self.0 - .get(ReadOptions::new(), k_bytes)? - .map(|bytes| { - if let Some(layout_verified) = - zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice( - &bytes[V::prefix_len()..], - ) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - )) - } - }) - .transpose() - }) - } - #[inline(always)] - fn delete<K: Key>(&mut self, k: &K) -> KvResult<()> { - k.as_bytes(|k_bytes| self.0.delete(WriteOptions::new(), k_bytes))?; - Ok(()) - } - #[inline(always)] - fn put<K: Key, V: Value>(&mut self, k: &K, value: &V) -> KvResult<()> { - value.as_bytes(|value_bytes| { - k.as_bytes(|k_bytes| self.0.put(WriteOptions::new(), k_bytes, value_bytes))?; - Ok(()) - }) - } - #[inline(always)] - fn write_batch(&mut self, inner_batch: Self::Batch) -> KvResult<()> { - self.0.write(WriteOptions::new(), &inner_batch.0)?; - Ok(()) - } - #[inline(always)] - fn iter<K: Key, V: Value>(&self, range: RangeBytes) -> Self::Iter { - LevelDbIter::new(self.0.iter(ReadOptions::new()), range) - } - #[inline(always)] - fn save(&self) -> KvResult<()> { - Ok(()) - } -} - -pub struct LevelDbIter { - inner: LevelDbIterator, - range_start: Bound<IVec>, - range_end: Bound<IVec>, - reversed: bool, -} -impl LevelDbIter { - fn new(inner: LevelDbIterator, range: RangeBytes) -> Self { - LevelDbIter { - inner, - range_start: range.0, - range_end: range.1, - reversed: false, - } - } -} -impl Debug for LevelDbIter { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("LevelDbIter") - .field("inner", &"LevelDbIterator<'db>") - .field("range_start", &self.range_start) - .field("range_end", &self.range_end) - .finish() - } -} - -impl Iterator for LevelDbIter { - type Item = Result<(LevelDbBytes, LevelDbBytes), DynErr>; - - #[inline(always)] - fn next(&mut self) -> Option<Self::Item> { - loop { - match self - .inner - .next() - .map(|(k, v)| Ok((LevelDbBytes(k), LevelDbBytes(v)))) - { - Some(Ok((key_bytes, value_bytes))) => { - let start_bound_ok = match &self.range_start { - Bound::Included(start_bytes) => key_bytes.as_ref() >= start_bytes.as_ref(), - Bound::Excluded(start_bytes) => key_bytes.as_ref() > start_bytes.as_ref(), - Bound::Unbounded => true, - }; - let end_bound_ok = match &self.range_end { - Bound::Included(end_bytes) => key_bytes.as_ref() <= end_bytes.as_ref(), - Bound::Excluded(end_bytes) => key_bytes.as_ref() < end_bytes.as_ref(), - Bound::Unbounded => true, - }; - if start_bound_ok { - if end_bound_ok { - break Some(Ok((key_bytes, value_bytes))); - } else if self.reversed { - // The interval has not yet begun. - continue; - } else { - // The range has been fully traversed, the iterator is finished. - break None; - } - } else if end_bound_ok { - if self.reversed { - // The range has been fully traversed, the iterator is finished. - break None; - } else { - // The interval has not yet begun. - continue; - } - } else { - // Empty range, the iterator is finished. - break None; - } - } - other => break other, - } - } - } -} -impl ReversableIterator for LevelDbIter { - #[inline(always)] - fn reverse(self) -> Self { - LevelDbIter { - range_start: self.range_start, - range_end: self.range_end, - reversed: !self.reversed, - inner: self.inner.reverse(), - } - } -} -impl BackendIter<LevelDbBytes, LevelDbBytes> for LevelDbIter {} - -#[derive(Clone, Debug)] -/// leveldb configuration -pub struct LevelDbConf { - pub create_if_missing: bool, - pub db_path: PathBuf, - pub error_if_exists: bool, - pub paranoid_checks: bool, - pub write_buffer_size: Option<usize>, - pub max_open_files: Option<i32>, - pub block_size: Option<usize>, - pub block_restart_interval: Option<i32>, - pub compression: bool, - pub cache: Option<usize>, -} - -impl LevelDbConf { - pub fn path(db_path: PathBuf) -> Self { - Self { - db_path, - ..Default::default() - } - } -} - -impl Default for LevelDbConf { - fn default() -> Self { - LevelDbConf { - create_if_missing: true, - db_path: PathBuf::default(), - error_if_exists: false, - paranoid_checks: false, - write_buffer_size: None, - max_open_files: None, - block_size: None, - block_restart_interval: None, - compression: true, - cache: None, - } - } -} - -impl Into<LevelDbOptions> for LevelDbConf { - fn into(self) -> LevelDbOptions { - LevelDbOptions { - create_if_missing: self.create_if_missing, - error_if_exists: self.error_if_exists, - paranoid_checks: self.paranoid_checks, - write_buffer_size: self.write_buffer_size, - max_open_files: self.max_open_files, - block_size: self.block_size, - block_restart_interval: self.block_restart_interval, - compression: if self.compression { - Compression::Snappy - } else { - Compression::No - }, - cache: self.cache.map(LevelDbCache::new), - } - } -} diff --git a/rust-libs/tools/kv_typed/src/backend/lmdb.rs b/rust-libs/tools/kv_typed/src/backend/lmdb.rs deleted file mode 100644 index a74d911c6..000000000 --- a/rust-libs/tools/kv_typed/src/backend/lmdb.rs +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Memory backend for KV Typed, - -use crate::*; -use lmdb::{traits::CreateCursor as _, LmdbResultExt as _}; -use lmdb_zero as lmdb; -use std::path::PathBuf; - -#[derive(Clone, Copy, Debug)] -/// Be careful with this backend -/// LMDB does not support multiple iterators in the same thread. So you need to make sure that : -/// 1. Any iterator must be drop before any new call to the `iter()` method. -/// 2. If you are in an asynchronous context, an async task should never yield when it to an instantiated iterator. -pub struct Lmdb; - -#[derive(Clone, Debug)] -pub struct LmdbConf { - folder_path: PathBuf, - temporary: bool, -} -impl Default for LmdbConf { - fn default() -> Self { - LmdbConf { - folder_path: PathBuf::default(), - temporary: false, - } - } -} -impl LmdbConf { - pub fn folder_path(mut self, folder_path: PathBuf) -> Self { - self.folder_path = folder_path; - self - } - pub fn temporary(mut self, temporary: bool) -> Self { - self.temporary = temporary; - self - } -} - -impl Backend for Lmdb { - const NAME: &'static str = "lmdb"; - type Col = LmdbCol; - type Conf = LmdbConf; - - fn open(conf: &Self::Conf) -> KvResult<Self> { - std::fs::create_dir_all(conf.folder_path.as_path())?; - Ok(Lmdb) - } - fn open_col(&mut self, conf: &Self::Conf, col_name: &str) -> KvResult<Self::Col> { - let path: PathBuf = conf.folder_path.join(col_name); - let exist = path.as_path().exists(); - if !exist { - std::fs::create_dir(path.as_path())?; - } - let path_to_remove = if conf.temporary { - Some(path.clone()) - } else { - None - }; - let path = path - .into_os_string() - .into_string() - .expect("Invalid DB path"); - let mut env_flags = lmdb::open::Flags::empty(); - env_flags.insert(lmdb::open::WRITEMAP); - env_flags.insert(lmdb::open::MAPASYNC); - env_flags.insert(lmdb::open::NOLOCK); - let col_options = if exist { - lmdb::DatabaseOptions::defaults() - } else { - lmdb::DatabaseOptions::new(lmdb::db::CREATE) - }; - let env = - std::sync::Arc::new(unsafe { lmdb::EnvBuilder::new()?.open(&path, env_flags, 0o600)? }); - let tree = std::sync::Arc::new(lmdb::Database::open(env.clone(), None, &col_options)?); - Ok(LmdbCol { - inner: LmdbColInner { env, tree }, - path_to_remove, - }) - } -} - -#[derive(Clone, Debug)] -pub struct LmdbCol { - inner: LmdbColInner, - path_to_remove: Option<PathBuf>, -} - -impl Drop for LmdbCol { - fn drop(&mut self) { - if let Some(ref path) = self.path_to_remove { - let _ = std::fs::remove_dir(path); - } - } -} - -#[derive(Clone, Debug)] -struct LmdbColInner { - env: std::sync::Arc<lmdb::Environment>, - tree: std::sync::Arc<lmdb::Database<'static>>, -} - -#[derive(Debug, Default)] -pub struct LmdbBatch { - upsert_ops: Vec<(IVec, IVec)>, - remove_ops: Vec<IVec>, -} - -impl BackendBatch for LmdbBatch { - fn upsert(&mut self, k: &[u8], v: &[u8]) { - self.upsert_ops.push((k.into(), v.into())); - } - - fn remove(&mut self, k: &[u8]) { - self.remove_ops.push(k.into()); - } -} - -#[derive(Debug)] -struct LmdbIterAccess { - env: std::sync::Arc<lmdb::Environment>, - access: lmdb::ConstAccessor<'static>, - tree: std::sync::Arc<lmdb::Database<'static>>, - tx: lmdb::ReadTransaction<'static>, -} - -#[derive(Debug)] -pub struct LmdbIter { - access: Arc<LmdbIterAccess>, - cursor: lmdb::Cursor<'static, 'static>, - reversed: bool, - started: bool, -} - -impl LmdbIter { - fn new( - env: std::sync::Arc<lmdb::Environment>, - tree: std::sync::Arc<lmdb::Database<'static>>, - ) -> Self { - let tx = lmdb::ReadTransaction::new(env.clone()).expect("fail to read DB"); - let tx_static: &'static lmdb::ReadTransaction<'static> = - unsafe { std::mem::transmute(&tx) }; - let access = tx_static.access(); - let cursor = tx_static - .cursor(tree.clone()) - .expect("fail to create DB cursor"); - LmdbIter { - access: Arc::new(LmdbIterAccess { - access, - env, - tree, - tx, - }), - cursor, - reversed: false, - started: false, - } - } -} - -impl Iterator for LmdbIter { - type Item = Result<(&'static [u8], &'static [u8]), DynErr>; - - fn next(&mut self) -> Option<Self::Item> { - if self.reversed { - if self.started { - match self - .cursor - .prev::<[u8], [u8]>(unsafe { - // # Safety - // Lifetime of accessor is used to track db and lmdb_tx lifetimes: These are already static. - // It's safe because the byte references will be transformed into K and V owned types before - // being exposed to the user API. - std::mem::transmute(&self.access.access) - }) - .to_opt() - { - Ok(Some((k, v))) => Some(Ok((k, v))), - Ok(None) => None, - Err(e) => Some(Err(e.into())), - } - } else { - self.started = true; - match self - .cursor - .last::<[u8], [u8]>(unsafe { - // # Safety - // Lifetime of accessor is used to track db and lmdb_tx lifetimes: These are already static. - // It's safe because the byte references will be transformed into K and V owned types before - // being exposed to the user API. - std::mem::transmute(&self.access.access) - }) - .to_opt() - { - Ok(Some((k, v))) => Some(Ok((k, v))), - Ok(None) => None, - Err(e) => Some(Err(e.into())), - } - } - } else if self.started { - match self - .cursor - .next::<[u8], [u8]>(unsafe { - // # Safety - // Lifetime of accessor is used to track db and lmdb_tx lifetimes: These are already static. - // It's safe because the byte references will be transformed into K and V owned types before - // being exposed to the user API. - std::mem::transmute(&self.access.access) - }) - .to_opt() - { - Ok(Some((k, v))) => Some(Ok((k, v))), - Ok(None) => None, - Err(e) => Some(Err(e.into())), - } - } else { - self.started = true; - match self - .cursor - .first::<[u8], [u8]>(unsafe { - // # Safety - // Lifetime of accessor is used to track db and lmdb_tx lifetimes: These are already static. - // It's safe because the byte references will be transformed into K and V owned types before - // being exposed to the user API. - std::mem::transmute(&self.access.access) - }) - .to_opt() - { - Ok(Some((k, v))) => Some(Ok((k, v))), - Ok(None) => None, - Err(e) => Some(Err(e.into())), - } - } - } -} - -impl ReversableIterator for LmdbIter { - fn reverse(mut self) -> Self { - self.reversed = true; - self - } -} - -impl BackendIter<&'static [u8], &'static [u8]> for LmdbIter {} - -impl BackendCol for LmdbCol { - type Batch = LmdbBatch; - type KeyBytes = &'static [u8]; - type ValueBytes = &'static [u8]; - type Iter = LmdbIter; - - fn get<K: Key, V: Value>(&self, k: &K) -> KvResult<Option<V>> { - let tx = lmdb::ReadTransaction::new(self.inner.tree.env())?; - let access = tx.access(); - k.as_bytes(|k_bytes| { - access - .get(&self.inner.tree, k_bytes) - .to_opt()? - .map(|bytes| V::from_bytes(&bytes).map_err(|e| KvError::DeserError(e.into()))) - .transpose() - }) - } - - fn get_ref<K: Key, V: ValueZc, D, F: Fn(&V::Ref) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>> { - k.as_bytes(|k_bytes| { - let tx = lmdb::ReadTransaction::new(self.inner.tree.env())?; - let access = tx.access(); - access - .get::<_, [u8]>(&self.inner.tree, k_bytes) - .to_opt()? - .map(|bytes| { - if let Some(layout_verified) = zerocopy::LayoutVerified::<_, V::Ref>::new(bytes) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".to_owned(), - )) - } - }) - .transpose() - }) - } - - fn get_ref_slice<K: Key, V: ValueSliceZc, D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>> { - k.as_bytes(|k_bytes| { - let tx = lmdb::ReadTransaction::new(self.inner.tree.env())?; - let access = tx.access(); - access - .get::<_, [u8]>(&self.inner.tree, k_bytes) - .to_opt()? - .map(|bytes| { - if let Some(layout_verified) = - zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice( - &bytes[V::prefix_len()..], - ) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".to_owned(), - )) - } - }) - .transpose() - }) - } - - fn clear(&mut self) -> KvResult<()> { - let tx = lmdb::WriteTransaction::new(self.inner.tree.env())?; - { - let mut access = tx.access(); - access.clear_db(&self.inner.tree)?; - } - tx.commit()?; - Ok(()) - } - - fn count(&self) -> KvResult<usize> { - let tx = lmdb::ReadTransaction::new(self.inner.tree.env())?; - Ok(tx.db_stat(&self.inner.tree)?.entries) - } - - fn iter<K: Key, V: Value>(&self, _range: RangeBytes) -> Self::Iter { - LmdbIter::new(self.inner.env.clone(), self.inner.tree.clone()) - } - - fn put<K: Key, V: Value>(&mut self, k: &K, value: &V) -> KvResult<()> { - value.as_bytes(|v_bytes| { - let tx = lmdb::WriteTransaction::new(self.inner.tree.env())?; - k.as_bytes(|k_bytes| { - let mut access = tx.access(); - access.put( - &self.inner.tree, - k_bytes, - v_bytes, - lmdb::put::Flags::empty(), - ) - })?; - tx.commit()?; - Ok(()) - }) - } - - fn delete<K: Key>(&mut self, k: &K) -> KvResult<()> { - let tx = lmdb::WriteTransaction::new(self.inner.tree.env())?; - k.as_bytes(|k_bytes| { - let mut access = tx.access(); - access.del_key(&self.inner.tree, k_bytes).to_opt() - })?; - tx.commit()?; - Ok(()) - } - - fn new_batch() -> Self::Batch { - LmdbBatch::default() - } - - fn write_batch(&mut self, inner_batch: Self::Batch) -> KvResult<()> { - let tx = lmdb::WriteTransaction::new(self.inner.tree.env())?; - { - let mut access = tx.access(); - for (k, v) in inner_batch.upsert_ops { - access.put( - &self.inner.tree, - k.as_ref(), - v.as_ref(), - lmdb::put::Flags::empty(), - )?; - } - for k in inner_batch.remove_ops { - access.del_key(&self.inner.tree, k.as_ref()).to_opt()?; - } - } - tx.commit()?; - Ok(()) - } - - fn save(&self) -> KvResult<()> { - Ok(self.inner.tree.env().sync(true)?) - } -} diff --git a/rust-libs/tools/kv_typed/src/backend/memory.rs b/rust-libs/tools/kv_typed/src/backend/memory.rs deleted file mode 100644 index f9c41870f..000000000 --- a/rust-libs/tools/kv_typed/src/backend/memory.rs +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Memory backend for KV Typed, - -use crate::*; -use std::collections::BTreeMap; -//use uninit::extension_traits::VecCapacity as _; - -#[derive(Clone, Copy, Debug)] -pub struct Mem; - -#[derive(Clone, Debug, Default)] -pub struct MemConf { - folder_path: Option<std::path::PathBuf>, -} - -type KeyBytes = IVec; -type ValueBytes = IVec; -type Tree = BTreeMap<KeyBytes, ValueBytes>; - -impl Backend for Mem { - const NAME: &'static str = "mem"; - type Col = MemCol; - type Conf = MemConf; - - fn open(_conf: &Self::Conf) -> KvResult<Self> { - Ok(Mem) - } - fn open_col(&mut self, _conf: &Self::Conf, _col_name: &str) -> KvResult<Self::Col> { - /*if let Some(ref folder_path) = conf.folder_path { - MemCol::from_file(folder_path.join(col_name)) - } else {*/ - Ok(MemCol { - path: None, - tree: BTreeMap::new(), - }) - //} - } -} - -#[derive(Debug, Default)] -pub struct MemBatch { - upsert_ops: Vec<(IVec, IVec)>, - remove_ops: Vec<IVec>, -} - -impl BackendBatch for MemBatch { - fn upsert(&mut self, k: &[u8], v: &[u8]) { - self.upsert_ops.push((k.into(), v.into())); - } - - fn remove(&mut self, k: &[u8]) { - self.remove_ops.push(k.into()); - } -} - -#[derive(Clone, Debug)] -pub struct MemCol { - path: Option<std::path::PathBuf>, - tree: Tree, -} - -impl BackendCol for MemCol { - type Batch = MemBatch; - type KeyBytes = KeyBytes; - type ValueBytes = ValueBytes; - type Iter = MemIter; - - #[inline(always)] - fn new_batch() -> Self::Batch { - MemBatch::default() - } - #[inline(always)] - fn clear(&mut self) -> KvResult<()> { - self.tree.clear(); - Ok(()) - } - #[inline(always)] - fn count(&self) -> KvResult<usize> { - Ok(self.tree.len()) - } - #[inline(always)] - fn contains_key<K: Key>(&self, k: &K) -> KvResult<bool> { - k.as_bytes(|k_bytes| Ok(self.tree.contains_key(k_bytes))) - } - #[inline(always)] - fn get<K: Key, V: Value>(&self, k: &K) -> KvResult<Option<V>> { - k.as_bytes(|k_bytes| { - self.tree - .get(k_bytes) - .map(|bytes| V::from_bytes(&bytes).map_err(|e| KvError::DeserError(e.into()))) - .transpose() - }) - } - #[inline(always)] - fn get_ref<K: Key, V: ValueZc, D, F: Fn(&V::Ref) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>> { - k.as_bytes(|k_bytes| { - self.tree - .get(k_bytes) - .map(|bytes| { - if let Some(layout_verified) = - zerocopy::LayoutVerified::<_, V::Ref>::new(bytes.as_ref()) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - )) - } - }) - .transpose() - }) - } - #[inline(always)] - fn get_ref_slice<K: Key, V: ValueSliceZc, D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>> { - k.as_bytes(|k_bytes| { - self.tree - .get(k_bytes) - .map(|bytes| { - if let Some(layout_verified) = - zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice( - &bytes[V::prefix_len()..], - ) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - )) - } - }) - .transpose() - }) - } - #[inline(always)] - fn delete<K: Key>(&mut self, k: &K) -> KvResult<()> { - k.as_bytes(|k_bytes| self.tree.remove(k_bytes)); - Ok(()) - } - #[inline(always)] - fn put<K: Key, V: Value>(&mut self, k: &K, value: &V) -> KvResult<()> { - value.as_bytes(|value_bytes| { - k.as_bytes(|k_bytes| { - self.tree.insert(k_bytes.into(), value_bytes.into()); - }); - Ok(()) - }) - } - #[inline(always)] - fn write_batch(&mut self, inner_batch: Self::Batch) -> KvResult<()> { - for (k, v) in inner_batch.upsert_ops { - self.tree.insert(k, v); - } - for k in inner_batch.remove_ops { - self.tree.remove(&k); - } - Ok(()) - } - #[inline(always)] - fn iter<K: Key, V: Value>(&self, range: RangeBytes) -> Self::Iter { - MemIter::new(unsafe { - // # Safety - // On front API, the iterator is given to a closure executed inside of a `ColRo` method, - // so that ensure borrowed tree keep alive - std::mem::transmute(self.tree.range(range)) - }) - } - #[inline(always)] - fn save(&self) -> KvResult<()> { - /*if let Some(ref file_path) = self.path { - let bytes = Self::tree_to_bytes(&self.tree); - - let mut file = - std::fs::File::create(file_path).map_err(|e| KvError::BackendError(e.into()))?; - use std::io::Write as _; - file.write_all(&bytes[..]) - .map_err(|e| KvError::BackendError(e.into()))?; - }*/ - - Ok(()) - } -} - -pub struct MemIter { - iter: std::collections::btree_map::Range<'static, KeyBytes, ValueBytes>, - reversed: bool, -} - -impl MemIter { - fn new( - tree_iter: std::collections::btree_map::Range<'static, KeyBytes, ValueBytes>, - ) -> MemIter { - MemIter { - iter: tree_iter, - reversed: false, - } - } -} - -impl Debug for MemIter { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("MemIter").field("0", &"???").finish() - } -} -impl Iterator for MemIter { - type Item = Result<(KeyBytes, ValueBytes), DynErr>; - - #[inline(always)] - fn next(&mut self) -> Option<Self::Item> { - if self.reversed { - self.iter.next_back() - } else { - self.iter.next() - } - .map(|(k, v)| Ok((k.to_owned(), v.to_owned()))) - } -} - -impl ReversableIterator for MemIter { - #[inline(always)] - fn reverse(mut self) -> Self { - self.reversed = !self.reversed; - self - } -} - -impl BackendIter<IVec, IVec> for MemIter {} - -#[cfg(test)] -mod tests { - /*use super::*; - - #[test] - fn test_save() -> KvResult<()> { - let mut tree = BTreeMap::new(); - - let k1 = IVec::from(&[1, 2, 3]); - let v1 = IVec::from(&[1, 2, 3, 4, 5]); - let k2 = IVec::from(&[1, 2]); - let v2 = IVec::from(&[]); - let k3 = IVec::from(&[1, 2, 3, 4, 5, 6, 7]); - let v3 = IVec::from(&[1, 2, 3, 4, 5, 6]); - let k4 = IVec::from(&[]); - let v4 = IVec::from(&[1, 2, 3, 4, 5, 6, 7]); - - tree.insert(k1.clone(), v1.clone()); - tree.insert(k2.clone(), v2.clone()); - tree.insert(k3.clone(), v3.clone()); - tree.insert(k4.clone(), v4.clone()); - - let bytes = MemCol::tree_to_bytes(&tree); - - let tree2 = MemCol::tree_from_bytes(&bytes)?; - - assert_eq!(tree2.len(), 4); - assert_eq!(tree2.get(&k1), Some(&v1)); - assert_eq!(tree2.get(&k2), Some(&v2)); - assert_eq!(tree2.get(&k3), Some(&v3)); - assert_eq!(tree2.get(&k4), Some(&v4)); - - Ok(()) - }*/ -} diff --git a/rust-libs/tools/kv_typed/src/backend/memory_singleton.rs b/rust-libs/tools/kv_typed/src/backend/memory_singleton.rs deleted file mode 100644 index 5f49a8cf3..000000000 --- a/rust-libs/tools/kv_typed/src/backend/memory_singleton.rs +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Memory backend for KV Typed, - -use crate::*; - -#[derive(Clone, Copy, Debug)] -pub struct MemSingleton; - -#[derive(Clone, Copy, Debug, Default)] -pub struct MemSingletonConf { - phantom: PhantomData<()>, -} - -type KeyBytes = IVec; -type ValueBytes = IVec; - -impl Backend for MemSingleton { - const NAME: &'static str = "mem_singleton"; - type Col = MemCol; - type Conf = MemSingletonConf; - - fn open(_conf: &Self::Conf) -> KvResult<Self> { - Ok(MemSingleton) - } - fn open_col(&mut self, _conf: &Self::Conf, _col_name: &str) -> KvResult<Self::Col> { - Ok(MemCol(None)) - } -} - -#[derive(Debug, Default)] -pub struct MemBatch(Option<IVec>); - -impl BackendBatch for MemBatch { - fn upsert(&mut self, _k: &[u8], v: &[u8]) { - self.0 = Some(v.into()); - } - - fn remove(&mut self, _k: &[u8]) { - self.0 = None; - } -} - -#[derive(Clone, Debug)] -pub struct MemCol(Option<ValueBytes>); - -impl BackendCol for MemCol { - type Batch = MemBatch; - type KeyBytes = KeyBytes; - type ValueBytes = ValueBytes; - type Iter = MemIter; - - #[inline(always)] - fn new_batch() -> Self::Batch { - MemBatch::default() - } - #[inline(always)] - fn clear(&mut self) -> KvResult<()> { - self.0 = None; - Ok(()) - } - #[inline(always)] - fn count(&self) -> KvResult<usize> { - if self.0.is_some() { - Ok(1) - } else { - Ok(0) - } - } - #[inline(always)] - fn contains_key<K: Key>(&self, _k: &K) -> KvResult<bool> { - Ok(self.0.is_some()) - } - #[inline(always)] - fn get<K: Key, V: Value>(&self, _k: &K) -> KvResult<Option<V>> { - self.0 - .as_ref() - .map(|bytes| V::from_bytes(bytes).map_err(|e| KvError::DeserError(e.into()))) - .transpose() - } - #[inline(always)] - fn get_ref<K: Key, V: ValueZc, D, F: Fn(&V::Ref) -> KvResult<D>>( - &self, - _k: &K, - f: F, - ) -> KvResult<Option<D>> { - self.0 - .as_ref() - .map(|bytes| { - if let Some(layout_verified) = - zerocopy::LayoutVerified::<_, V::Ref>::new(bytes.as_ref()) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - )) - } - }) - .transpose() - } - #[inline(always)] - fn get_ref_slice<K: Key, V: ValueSliceZc, D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - _k: &K, - f: F, - ) -> KvResult<Option<D>> { - self.0 - .as_ref() - .map(|bytes| { - if let Some(layout_verified) = - zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice(&bytes[V::prefix_len()..]) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - )) - } - }) - .transpose() - } - #[inline(always)] - fn delete<K: Key>(&mut self, _k: &K) -> KvResult<()> { - self.0 = None; - Ok(()) - } - #[inline(always)] - fn put<K: Key, V: Value>(&mut self, _k: &K, value: &V) -> KvResult<()> { - value.as_bytes(|value_bytes| { - self.0 = Some(value_bytes.into()); - Ok(()) - }) - } - #[inline(always)] - fn write_batch(&mut self, inner_batch: Self::Batch) -> KvResult<()> { - self.0 = inner_batch.0; - Ok(()) - } - #[inline(always)] - fn iter<K: Key, V: Value>(&self, _: RangeBytes) -> Self::Iter { - MemIter(self.0.clone()) - } - #[inline(always)] - fn save(&self) -> KvResult<()> { - Ok(()) - } -} - -pub struct MemIter(Option<ValueBytes>); - -impl Debug for MemIter { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("MemIter").field("0", &"???").finish() - } -} -impl Iterator for MemIter { - type Item = Result<(KeyBytes, ValueBytes), DynErr>; - - #[inline(always)] - fn next(&mut self) -> Option<Self::Item> { - self.0.take().map(|v| Ok((KeyBytes::default(), v))) - } -} - -impl ReversableIterator for MemIter { - #[inline(always)] - fn reverse(self) -> Self { - self - } -} - -impl BackendIter<IVec, IVec> for MemIter {} diff --git a/rust-libs/tools/kv_typed/src/backend/mock.rs b/rust-libs/tools/kv_typed/src/backend/mock.rs deleted file mode 100644 index 0d479a398..000000000 --- a/rust-libs/tools/kv_typed/src/backend/mock.rs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed mock backend - -use super::MockBackendBatch; -use crate::*; - -mockall::mock! { - pub BackendIter {} - trait Iterator { - type Item = Result<(IVec, IVec), DynErr>; - - fn next(&mut self) -> Option<<Self as Iterator>::Item>; - } - trait ReversableIterator { - fn reverse(self) -> Self; - } -} -impl BackendIter<IVec, IVec> for MockBackendIter {} - -mockall::mock! { - pub BackendCol {} - trait Clone { - fn clone(&self) -> Self; - } - trait BackendCol { - type Batch = MockBackendBatch; - type KeyBytes = IVec; - type ValueBytes = IVec; - type Iter = MockBackendIter; - - fn get<K: Key, V: Value>(&self, k: &K) -> KvResult<Option<V>>; - fn get_ref<K: Key, V: ValueZc, D, F: Fn(&V::Ref) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>>; - fn get_ref_slice<K: Key, V: ValueSliceZc, D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>>; - fn clear(&self) -> KvResult<()>; - fn count(&self) -> KvResult<usize>; - fn iter<K: Key, V: Value>(&self, range: RangeBytes) -> MockBackendIter; - fn put<K: Key, V: Value>(&self, k: &K, value: &V) -> KvResult<()>; - fn delete<K: Key>(&self, k: &K) -> KvResult<()>; - fn new_batch() -> MockBackendBatch; - fn write_batch(&self, inner_batch: MockBackendBatch) -> KvResult<()>; - fn save(&self) -> KvResult<()>; - } -} -impl Debug for MockBackendCol { - fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - unimplemented!() - } -} - -mockall::mock! { - pub Backend {} - trait Clone { - fn clone(&self) -> Self; - } - trait Backend: 'static + Clone + Sized { - const NAME: &'static str = "mock"; - type Col = MockBackendCol; - type Conf = (); - - fn open(conf: &()) -> KvResult<Self>; - fn open_col(&mut self, conf: &(), col_name: &str) -> KvResult<MockBackendCol>; - } -} diff --git a/rust-libs/tools/kv_typed/src/backend/sled.rs b/rust-libs/tools/kv_typed/src/backend/sled.rs deleted file mode 100644 index 3f97ef6de..000000000 --- a/rust-libs/tools/kv_typed/src/backend/sled.rs +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Sled backend for KV Typed, - -pub use sled::Config; - -use crate::*; - -#[derive(Clone, Debug)] -pub struct Sled { - db: sled::Db, - trees: Vec<sled::Tree>, -} - -impl Backend for Sled { - const NAME: &'static str = "sled"; - type Col = SledCol; - type Conf = Config; - - fn open(conf: &Self::Conf) -> KvResult<Self> { - Ok(Sled { - db: conf.open()?, - trees: Vec::new(), - }) - } - fn open_col(&mut self, _conf: &Self::Conf, col_name: &str) -> KvResult<Self::Col> { - let tree = self.db.open_tree(col_name)?; - self.trees.push(tree.clone()); - Ok(SledCol(tree)) - } -} - -impl BackendBatch for sled::Batch { - fn upsert(&mut self, k: &[u8], v: &[u8]) { - self.insert(k, v) - } - - fn remove(&mut self, k: &[u8]) { - self.remove(k) - } -} - -#[derive(Clone, Debug)] -pub struct SledCol(sled::Tree); - -impl BackendCol for SledCol { - type Batch = sled::Batch; - type KeyBytes = IVec; - type ValueBytes = IVec; - type Iter = SledIter; - - #[inline(always)] - fn new_batch() -> Self::Batch { - sled::Batch::default() - } - #[inline(always)] - fn clear(&mut self) -> KvResult<()> { - self.0.clear()?; - Ok(()) - } - #[inline(always)] - fn count(&self) -> KvResult<usize> { - Ok(self.0.len()) - } - #[inline(always)] - fn contains_key<K: Key>(&self, k: &K) -> KvResult<bool> { - k.as_bytes(|k_bytes| Ok(self.0.contains_key(k_bytes)?)) - } - #[inline(always)] - fn get<K: Key, V: Value>(&self, k: &K) -> KvResult<Option<V>> { - k.as_bytes(|k_bytes| { - self.0 - .get(k_bytes)? - .map(|bytes| V::from_bytes(&bytes).map_err(|e| KvError::DeserError(e.into()))) - .transpose() - }) - } - #[inline(always)] - fn get_ref<K: Key, V: ValueZc, D, F: Fn(&V::Ref) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>> { - k.as_bytes(|k_bytes| { - self.0 - .get(k_bytes)? - .map(|bytes| { - if let Some(layout_verified) = - zerocopy::LayoutVerified::<_, V::Ref>::new(bytes.as_ref()) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - )) - } - }) - .transpose() - }) - } - #[inline(always)] - fn get_ref_slice<K: Key, V: ValueSliceZc, D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &K, - f: F, - ) -> KvResult<Option<D>> { - k.as_bytes(|k_bytes| { - self.0 - .get(k_bytes)? - .map(|bytes| { - if let Some(layout_verified) = - zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice( - &bytes[V::prefix_len()..], - ) - { - f(&layout_verified) - } else { - Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - )) - } - }) - .transpose() - }) - } - #[inline(always)] - fn delete<K: Key>(&mut self, k: &K) -> KvResult<()> { - k.as_bytes(|k_bytes| self.0.remove(k_bytes))?; - Ok(()) - } - #[inline(always)] - fn put<K: Key, V: Value>(&mut self, k: &K, value: &V) -> KvResult<()> { - value.as_bytes(|value_bytes| { - k.as_bytes(|k_bytes| self.0.insert(k_bytes, value_bytes))?; - Ok(()) - }) - } - #[inline(always)] - fn write_batch(&mut self, inner_batch: Self::Batch) -> KvResult<()> { - self.0.apply_batch(inner_batch)?; - Ok(()) - } - #[inline(always)] - fn iter<K: Key, V: Value>(&self, range: RangeBytes) -> Self::Iter { - SledIter { - iter: self.0.range(range), - reversed: false, - } - } - #[inline(always)] - fn save(&self) -> KvResult<()> { - self.0.flush()?; - Ok(()) - } -} - -pub struct SledIter { - iter: sled::Iter, - reversed: bool, -} - -impl Debug for SledIter { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("SledIter") - .field("0", &"sled::Iter") - .finish() - } -} -impl Iterator for SledIter { - type Item = Result<(IVec, IVec), DynErr>; - - #[inline(always)] - fn next(&mut self) -> Option<Self::Item> { - if self.reversed { - self.iter.next_back() - } else { - self.iter.next() - } - .map(|res| res.map_err(Box::new).map_err(Into::into)) - } -} -impl ReversableIterator for SledIter { - #[inline(always)] - fn reverse(self) -> Self { - SledIter { - iter: self.iter, - reversed: !self.reversed, - } - } -} - -impl BackendIter<IVec, IVec> for SledIter {} diff --git a/rust-libs/tools/kv_typed/src/batch.rs b/rust-libs/tools/kv_typed/src/batch.rs deleted file mode 100644 index 51d120ea6..000000000 --- a/rust-libs/tools/kv_typed/src/batch.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; -use std::collections::{BTreeMap, HashMap, HashSet}; - -#[derive(Debug)] -pub struct Batch<BC: BackendCol, C: DbCollectionRw> { - phantom: PhantomData<BC>, - pub(crate) tree: BTreeMap<IVec, Option<IVec>>, - upsert_ops: HashMap<C::K, C::V>, - delete_ops: HashSet<C::K>, -} - -#[derive(Debug, PartialEq)] -pub enum BatchGet<'v, V: Value> { - None, - Deleted, - Updated(&'v V), -} - -impl<BC: BackendCol, C: DbCollectionRw> Default for Batch<BC, C> { - fn default() -> Self { - Batch { - phantom: PhantomData, - tree: BTreeMap::default(), - upsert_ops: HashMap::default(), - delete_ops: HashSet::default(), - } - } -} - -impl<BC: BackendCol, C: DbCollectionRw> Batch<BC, C> { - pub fn clear(&mut self) { - self.tree.clear(); - self.upsert_ops.clear(); - self.delete_ops.clear(); - } - pub fn get(&self, k: &C::K) -> BatchGet<C::V> { - if self.delete_ops.contains(k) { - BatchGet::Deleted - } else if let Some(v) = self.upsert_ops.get(k) { - BatchGet::Updated(v) - } else { - BatchGet::None - } - } - pub fn upsert(&mut self, k: C::K, v: C::V) { - let _ = k.as_bytes(|k_bytes| { - v.as_bytes(|v_bytes| { - self.tree - .insert(IVec::from(k_bytes), Some(IVec::from(v_bytes))); - }) - }); - self.upsert_ops.insert(k, v); - } - pub fn remove(&mut self, k: C::K) { - let _ = k.as_bytes(|k_bytes| { - self.tree.insert(IVec::from(k_bytes), None); - }); - self.upsert_ops.remove(&k); - self.delete_ops.insert(k); - } - #[doc(hidden)] - pub fn into_backend_batch(self) -> BC::Batch { - let mut backend_batch = BC::Batch::default(); - for (k_bytes, v_bytes_opt) in self.tree { - if let Some(v_bytes) = v_bytes_opt { - backend_batch.upsert(k_bytes.as_ref(), v_bytes.as_ref()); - } else { - backend_batch.remove(k_bytes.as_ref()); - } - } - backend_batch - } - #[doc(hidden)] - pub fn into_backend_batch_and_events(self) -> (BC::Batch, SmallVec<[C::Event; 4]>) { - let mut backend_batch = BC::Batch::default(); - for (k_bytes, v_bytes_opt) in self.tree { - if let Some(v_bytes) = v_bytes_opt { - backend_batch.upsert(k_bytes.as_ref(), v_bytes.as_ref()); - } else { - backend_batch.remove(k_bytes.as_ref()); - } - } - let mut events: SmallVec<[C::Event; 4]> = self - .upsert_ops - .into_iter() - .map(|(k, v)| C::Event::upsert(k, v)) - .collect(); - events.extend(self.delete_ops.into_iter().map(C::Event::remove)); - (backend_batch, events) - } -} diff --git a/rust-libs/tools/kv_typed/src/bytes.rs b/rust-libs/tools/kv_typed/src/bytes.rs deleted file mode 100644 index 54a4d29dd..000000000 --- a/rust-libs/tools/kv_typed/src/bytes.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed bytes - -use crate::*; - -pub trait KeyBytes: AsRef<[u8]> + Debug + Ord {} -impl<T> KeyBytes for T where T: AsRef<[u8]> + Debug + Ord {} -pub trait ValueBytes: AsRef<[u8]> + Debug {} -impl<T> ValueBytes for T where T: AsRef<[u8]> + Debug {} - -#[derive(Debug, Eq, PartialEq)] -pub enum CowKB<'a, B: KeyBytes> { - B(&'a [u8]), - O(B), -} -impl<'a, B: KeyBytes> AsRef<[u8]> for CowKB<'a, B> { - fn as_ref(&self) -> &[u8] { - match self { - CowKB::B(b_ref) => b_ref, - CowKB::O(b) => b.as_ref(), - } - } -} - -impl<'a, B: KeyBytes> PartialOrd for CowKB<'a, B> { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - self.as_ref().partial_cmp(other.as_ref()) - } -} -impl<'a, B: KeyBytes> Ord for CowKB<'a, B> { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.as_ref().cmp(other.as_ref()) - } -} - -#[derive(Debug)] -pub enum CowVB<'a, B: ValueBytes> { - B(&'a [u8]), - O(B), -} -impl<'a, B: ValueBytes> AsRef<[u8]> for CowVB<'a, B> { - fn as_ref(&self) -> &[u8] { - match self { - CowVB::B(b_ref) => b_ref, - CowVB::O(b) => b.as_ref(), - } - } -} diff --git a/rust-libs/tools/kv_typed/src/collection_inner.rs b/rust-libs/tools/kv_typed/src/collection_inner.rs deleted file mode 100644 index 452cc3f79..000000000 --- a/rust-libs/tools/kv_typed/src/collection_inner.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -use crate::*; - -#[derive(Debug)] -pub struct ColInner<BC: BackendCol, E: EventTrait> { - pub(crate) backend_col: BC, - subscribers: ColSubscribers<E>, -} - -impl<BC: BackendCol, E: EventTrait> ColInner<BC, E> { - pub(crate) fn new(backend_col: BC) -> (Self, SubscriptionsSender<E>) { - let subscribers = ColSubscribers::<E>::default(); - let subscription_sender = subscribers.get_subscription_sender(); - - ( - ColInner { - backend_col, - subscribers, - }, - subscription_sender, - ) - } - pub(crate) fn notify_subscribers(&mut self, events: Events<E>) { - // Add new subscribers, notify all subscribers them prune died subscribers - self.subscribers.add_new_subscribers(); - let died_subscribers = self.subscribers.notify_subscribers(Arc::new(events)); - self.subscribers.prune_subscribers(died_subscribers); - } -} diff --git a/rust-libs/tools/kv_typed/src/collection_ro.rs b/rust-libs/tools/kv_typed/src/collection_ro.rs deleted file mode 100644 index 1ab536010..000000000 --- a/rust-libs/tools/kv_typed/src/collection_ro.rs +++ /dev/null @@ -1,267 +0,0 @@ -use crate::*; - -pub trait DbCollectionRo: Sized { - type BackendCol: BackendCol; - type K: Key; - type V: Value; - type Event: EventTrait<K = Self::K, V = Self::V>; - - fn contains_key(&self, k: &Self::K) -> KvResult<bool>; - fn count(&self) -> KvResult<usize>; - fn get(&self, k: &Self::K) -> KvResult<Option<Self::V>>; - /// Don't worry about complex iter type. Use it like an `impl Iterator<Item=KvResult<(K, V)>>`. - fn iter< - D: Send + Sync, - R: 'static + RangeBounds<Self::K>, - F: FnOnce( - KvIter< - Self::BackendCol, - <Self::BackendCol as BackendCol>::KeyBytes, - <Self::BackendCol as BackendCol>::ValueBytes, - <Self::BackendCol as BackendCol>::Iter, - Self::K, - Self::V, - >, - ) -> D, - >( - &self, - range: R, - f: F, - ) -> D; - /// Don't worry about complex iter type. Use it like an `impl Iterator<Item=KvResult<(K, V)>>`. - fn iter_rev< - D: Send + Sync, - R: 'static + RangeBounds<Self::K>, - F: FnOnce( - KvIter< - Self::BackendCol, - <Self::BackendCol as BackendCol>::KeyBytes, - <Self::BackendCol as BackendCol>::ValueBytes, - <Self::BackendCol as BackendCol>::Iter, - Self::K, - Self::V, - >, - ) -> D, - >( - &self, - range: R, - f: F, - ) -> D; - fn subscribe(&self, subscriber_sender: Subscriber<Self::Event>) -> KvResult<()>; -} - -#[cfg(feature = "mock")] -mockall::mock! { - pub ColRo<E: EventTrait> {} - trait DbCollectionRo { - type BackendCol = MockBackendCol; - type K = E::K; - type V = E::V; - type Event = E; - - fn count(&self) -> KvResult<usize>; - fn get(&self, k: &E::K) -> KvResult<Option<E::V>>; - fn iter<R: 'static + RangeBounds<E::K>>(&self, range: R) - -> KvIter<MockBackendCol, MockBackendIter, E::K, E::V>; - fn subscribe(&self, subscriber_sender: Subscriber<E>) -> KvResult<()>; - } -} - -type ColRoReader<'r, BC, E> = parking_lot::RwLockReadGuard<'r, ColInner<BC, E>>; - -#[derive(Debug)] -pub struct ColRo<BC: BackendCol, E: EventTrait> { - pub(crate) inner: Arc<parking_lot::RwLock<ColInner<BC, E>>>, - pub(crate) subscription_sender: SubscriptionsSender<E>, -} - -impl<BC: BackendCol, E: EventTrait> Clone for ColRo<BC, E> { - fn clone(&self) -> Self { - Self { - inner: Arc::clone(&self.inner), - subscription_sender: self.subscription_sender.clone(), - } - } -} -impl<BC: BackendCol, E: EventTrait> DbCollectionRo for ColRo<BC, E> { - type BackendCol = BC; - type K = E::K; - type V = E::V; - type Event = E; - - #[inline(always)] - fn contains_key(&self, k: &Self::K) -> KvResult<bool> { - let r = self.inner.read(); - r.backend_col.contains_key(k) - } - #[inline(always)] - fn count(&self) -> KvResult<usize> { - let r = self.inner.read(); - r.backend_col.count() - } - #[inline(always)] - fn get(&self, k: &Self::K) -> KvResult<Option<Self::V>> { - let r = self.inner.read(); - r.backend_col.get(k) - } - #[inline(always)] - fn iter< - D: Send + Sync, - R: 'static + RangeBounds<Self::K>, - F: FnOnce( - KvIter< - Self::BackendCol, - <Self::BackendCol as BackendCol>::KeyBytes, - <Self::BackendCol as BackendCol>::ValueBytes, - <Self::BackendCol as BackendCol>::Iter, - Self::K, - Self::V, - >, - ) -> D, - >( - &self, - range: R, - f: F, - ) -> D { - let range: RangeBytes = crate::iter::convert_range::<Self::K, R>(range); - let r = self.inner.read(); - let iter = r.backend_col.iter::<Self::K, Self::V>(range); - f(KvIter::new(iter)) - } - #[inline(always)] - fn iter_rev< - D: Send + Sync, - R: 'static + RangeBounds<Self::K>, - F: FnOnce( - KvIter< - Self::BackendCol, - <Self::BackendCol as BackendCol>::KeyBytes, - <Self::BackendCol as BackendCol>::ValueBytes, - <Self::BackendCol as BackendCol>::Iter, - Self::K, - Self::V, - >, - ) -> D, - >( - &self, - range: R, - f: F, - ) -> D { - let range: RangeBytes = crate::iter::convert_range::<Self::K, R>(range); - let r = self.inner.read(); - let iter = r.backend_col.iter::<Self::K, Self::V>(range).reverse(); - f(KvIter::new(iter)) - } - #[inline(always)] - fn subscribe(&self, subscriber_sender: Subscriber<Self::Event>) -> KvResult<()> { - self.subscription_sender - .try_send(subscriber_sender) - .map_err(|_| KvError::FailToSubscribe) - } -} - -pub trait DbCollectionRoGetRef<V: ValueZc>: DbCollectionRo<V = V> { - fn get_ref<D, F: Fn(&V::Ref) -> KvResult<D>>( - &self, - k: &<Self as DbCollectionRo>::K, - f: F, - ) -> KvResult<Option<D>>; -} - -impl<V: ValueZc, BC: BackendCol, E: EventTrait<V = V>> DbCollectionRoGetRef<V> for ColRo<BC, E> { - fn get_ref<D, F: Fn(&V::Ref) -> KvResult<D>>(&self, k: &E::K, f: F) -> KvResult<Option<D>> { - let r = self.inner.read(); - r.backend_col.get_ref::<E::K, V, D, F>(k, f) - } -} - -pub trait DbCollectionRoGetRefSlice<V: ValueSliceZc>: DbCollectionRo<V = V> { - fn get_ref_slice<D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &<Self as DbCollectionRo>::K, - f: F, - ) -> KvResult<Option<D>>; -} - -impl<V: ValueSliceZc, BC: BackendCol, E: EventTrait<V = V>> DbCollectionRoGetRefSlice<V> - for ColRo<BC, E> -{ - fn get_ref_slice<D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &E::K, - f: F, - ) -> KvResult<Option<D>> { - let r = self.inner.read(); - r.backend_col.get_ref_slice::<E::K, V, D, F>(k, f) - } -} - -pub trait DbCollectionRoIterRefSlice<'r, BC: BackendCol, K: KeyZc, V: ValueSliceZc, READER>: - DbCollectionRo<K = K, V = V> -{ - fn iter_ref_slice<D, R, F>(&'r self, range: R, f: F) -> KvIterRefSlice<BC, D, K, V, F, READER> - where - K: KeyZc, - V: ValueSliceZc, - R: 'static + RangeBounds<K>, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>; - fn iter_ref_slice_rev<D, R, F>( - &'r self, - range: R, - f: F, - ) -> KvIterRefSlice<BC, D, K, V, F, READER> - where - K: KeyZc, - V: ValueSliceZc, - R: 'static + RangeBounds<K>, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>; -} - -impl<'r, K: KeyZc, V: ValueSliceZc, BC: BackendCol, E: EventTrait<K = K, V = V>> - DbCollectionRoIterRefSlice<'r, BC, K, V, ColRoReader<'r, BC, E>> for ColRo<BC, E> -{ - fn iter_ref_slice<D, R, F>( - &'r self, - range: R, - f: F, - ) -> KvIterRefSlice<BC, D, K, V, F, ColRoReader<'r, BC, E>> - where - K: KeyZc, - V: ValueSliceZc, - R: 'static + RangeBounds<K>, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, - { - let range: RangeBytes = crate::iter::convert_range::<Self::K, R>(range); - let reader = self.inner.read(); - let inner_iter = reader.backend_col.iter_ref_slice::<D, K, V, F>(range, f); - - KvIterRefSlice { - inner: inner_iter, - reader: OwnedOrRef::Owned(reader), - } - } - - fn iter_ref_slice_rev<D, R, F>( - &'r self, - range: R, - f: F, - ) -> KvIterRefSlice<BC, D, K, V, F, ColRoReader<'r, BC, E>> - where - K: KeyZc, - V: ValueSliceZc, - R: 'static + RangeBounds<K>, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, - { - let range: RangeBytes = crate::iter::convert_range::<Self::K, R>(range); - let reader = self.inner.read(); - let inner_iter = reader - .backend_col - .iter_ref_slice::<D, K, V, F>(range, f) - .reverse(); - - KvIterRefSlice { - inner: inner_iter, - reader: OwnedOrRef::Owned(reader), - } - } -} diff --git a/rust-libs/tools/kv_typed/src/collection_rw.rs b/rust-libs/tools/kv_typed/src/collection_rw.rs deleted file mode 100644 index 13ab15956..000000000 --- a/rust-libs/tools/kv_typed/src/collection_rw.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::*; -use parking_lot::{ - RwLockUpgradableReadGuard as UpgradableReadGuard, RwLockWriteGuard as WriteGuard, -}; - -pub trait DbCollectionRw { - type K: Key; - type V: Value; - type Event: EventTrait<K = Self::K, V = Self::V>; - - fn clear(&self) -> KvResult<()>; - fn remove(&self, k: Self::K) -> KvResult<()>; - fn save(&self) -> KvResult<()>; - fn upsert(&self, k: Self::K, v: Self::V) -> KvResult<()>; -} - -#[derive(Debug)] -pub struct ColRw<BC: BackendCol, E: EventTrait> { - pub(crate) inner: ColRo<BC, E>, -} - -impl<BC: BackendCol, E: EventTrait> Clone for ColRw<BC, E> { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } -} - -impl<BC: BackendCol, E: EventTrait> DbCollectionRw for ColRw<BC, E> { - type K = E::K; - type V = E::V; - type Event = E; - - fn clear(&self) -> KvResult<()> { - let mut w = self.inner.inner.write(); - w.backend_col.clear()?; - let events = smallvec::smallvec![E::clear()]; - w.notify_subscribers(events); - Ok(()) - } - fn remove(&self, k: Self::K) -> KvResult<()> { - let mut w = self.inner.inner.write(); - w.backend_col.delete(&k)?; - let events = smallvec::smallvec![E::remove(k)]; - w.notify_subscribers(events); - Ok(()) - } - fn save(&self) -> KvResult<()> { - let w = self.inner.inner.write(); - w.backend_col.save()?; - Ok(()) - } - fn upsert(&self, k: Self::K, v: Self::V) -> KvResult<()> { - let mut w = self.inner.inner.write(); - w.backend_col.put(&k, &v)?; - let events = smallvec::smallvec![E::upsert(k, v)]; - w.notify_subscribers(events); - Ok(()) - } -} - -impl<BC: BackendCol, E: EventTrait> ColRw<BC, E> { - pub fn new(backend_col: BC) -> Self { - let (col_inner, subscription_sender) = ColInner::new(backend_col); - Self { - inner: ColRo { - inner: Arc::new(parking_lot::RwLock::new(col_inner)), - subscription_sender, - }, - } - } - pub fn to_ro(&self) -> &ColRo<BC, E> { - &self.inner - } - #[doc(hidden)] - /// For internal usage only MUST NOT USE - pub fn upgradable_read(&self) -> UpgradableReadGuard<'_, ColInner<BC, E>> { - self.inner.inner.upgradable_read() - } - pub fn write_batch(&self, batch: Batch<BC, Self>) -> KvResult<()> { - let (backend_batch, events) = batch.into_backend_batch_and_events(); - let mut w = self.inner.inner.write(); - w.backend_col.write_batch(backend_batch)?; - w.notify_subscribers(events); - Ok(()) - } - #[doc(hidden)] - /// For internal usage only MUST NOT USE - pub fn write_backend_batch( - &self, - backend_batch: BC::Batch, - events: Events<E>, - write_guard: &mut WriteGuard<ColInner<BC, E>>, - ) -> KvResult<()> { - write_guard.backend_col.write_batch(backend_batch)?; - write_guard.notify_subscribers(events); - Ok(()) - } -} diff --git a/rust-libs/tools/kv_typed/src/db_schema.rs b/rust-libs/tools/kv_typed/src/db_schema.rs deleted file mode 100644 index 657d7797d..000000000 --- a/rust-libs/tools/kv_typed/src/db_schema.rs +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -#[macro_export] -macro_rules! db_schema { - ($db_name:ident, [ $([$col_path:literal, $col_name:ident, $K:ty, $V:ty]),*, ]) => { - paste::paste! { - $( - // Define each collection event type - #[derive(Debug, PartialEq)] - pub enum [<$col_name Event>] { - Upsert { key: $K, value: $V }, - Remove { key: $K }, - RemoveAll, - } - impl kv_typed::prelude::EventTrait for [<$col_name Event>] { - type K = $K; - type V = $V; - - fn clear() -> Self { Self::RemoveAll } - fn upsert(k: Self::K, v: Self::V) -> Self { Self::Upsert { key: k, value: v, } } - fn remove(k: Self::K) -> Self { Self::Remove { key: k } } - } - )* - // Inner module used to hide internals types that must not be exposed on public api - pub use __inner::{[<$db_name Db>], [<$db_name DbRo>], [<$db_name DbWritable>], [<$db_name DbReadable>], [<$db_name DbTxRw>]}; - mod __inner { - use super::*; - use kv_typed::prelude::*; - // DbCollections - #[derive(Clone, Debug)] - pub struct [<$db_name ColsRo>]<BC: BackendCol> { - $([<$col_name:snake>]: ColRo<BC, [<$col_name Event>]>,)* - } - #[derive(Clone, Debug)] - pub struct [<$db_name ColsRw>]<BC: BackendCol> { - $([<$col_name:snake>]: ColRw<BC, [<$col_name Event>]>,)* - } - impl<BC: BackendCol> [<$db_name ColsRw>]<BC> { - fn to_ro(&self) -> [<$db_name ColsRo>]<BC> { - [<$db_name ColsRo>] { - $([<$col_name:snake>]: self.[<$col_name:snake>].to_ro().clone(),)* - } - } - } - // Db - #[derive(Debug)] - pub struct [<$db_name Db>]<B: Backend> { - collections: [<$db_name ColsRw>]<B::Col>, - } - impl<B: Backend> [<$db_name Db>]<B> { - pub const NAME: &'static str = stringify!([<$db_name:snake>]); - } - impl<B: Backend> Clone for [<$db_name Db>]<B> { - fn clone(&self) -> Self { - [<$db_name Db>] { - collections: self.collections.clone(), - } - } - } - #[cfg(feature = "explorer")] - impl<B: Backend> kv_typed::explorer::DbExplorable for [<$db_name Db>]<B> { - fn explore<'a>( - &self, - collection_name: &str, - action: kv_typed::explorer::ExplorerAction<'a>, - stringify_json_value: fn(serde_json::Value) -> serde_json::Value, - ) -> KvResult<std::result::Result<kv_typed::explorer::ExplorerActionResponse, ExplorerActionErr>> { - $( if stringify!([<$col_name:snake>]) == collection_name { - return action.exec(&self.collections.[<$col_name:snake>], stringify_json_value); - } )* - Ok(Err(ExplorerActionErr(format!("collection '{}' not exist in database '{}'.", collection_name, stringify!([<$db_name Db>])).into()))) - } - fn list_collections() -> Vec<(&'static str, &'static str, &'static str)> { - vec![ - $((stringify!([<$col_name:snake>]), stringify!($K), stringify!($V)),)* - ] - } - } - // Batch - pub struct [<$db_name DbBatch>]<B: Backend> { - $([<$col_name:snake>]: Batch<B::Col, ColRw<B::Col, [<$col_name Event>]>>,)* - } - impl<B: Backend> Default for [<$db_name DbBatch>]<B> { - fn default() -> Self { - [<$db_name DbBatch>] { - $([<$col_name:snake>]: Batch::default(),)* - } - } - } - impl<B: Backend> [<$db_name DbBatch>]<B> { - $(pub fn [<$col_name:snake>](&mut self) -> &mut Batch<B::Col, ColRw<B::Col, [<$col_name Event>]>> { &mut self.[<$col_name:snake>] })* - } - // impl TransactionalWrite for Db - #[derive(Debug)] - pub struct [<$db_name DbTxRw>]<'tx, BC: BackendCol> { - $(pub [<$col_name:snake>]: TxColRw<'tx, BC, [<$col_name Event>]>,)* - } - impl<'tx, B: Backend> TransactionalWrite<'tx, B::Col> for &'tx [<$db_name Db>]<B> { - type TxCols = [<$db_name DbTxRw>]<'tx, B::Col>; - - fn write<D, F: FnOnce(Self::TxCols) -> KvResult<D>>(&'tx self, f: F) -> KvResult<D> { - $(let [<$col_name:snake _upgradable_guard>] = self.collections.[<$col_name:snake>].upgradable_read();)* - - $(let mut [<$col_name:snake _batch>] = Batch::<B::Col, ColRw<B::Col, [<$col_name Event>]>>::default();)* - - let db_tx = [<$db_name DbTxRw>] { - $([<$col_name:snake>]: TxColRw::new( - unsafe { std::mem::transmute(&mut [<$col_name:snake _batch>]) }, - unsafe { std::mem::transmute(&[<$col_name:snake _upgradable_guard>]) }, - ),)* - }; - - let data = f(db_tx)?; - - // Prepare commit - $(let ([<$col_name:snake _backend_batch>], [<$col_name:snake _events>]) = [<$col_name:snake _batch>].into_backend_batch_and_events();)* - - // Acquire exclusive lock - $(let mut [<$col_name:snake _write_guard>] = parking_lot::RwLockUpgradableReadGuard::upgrade([<$col_name:snake _upgradable_guard>]);)*; - - // Commit - $(self.collections.[<$col_name:snake>].write_backend_batch( - [<$col_name:snake _backend_batch>], - [<$col_name:snake _events>], - &mut [<$col_name:snake _write_guard>], - )?;)* - - Ok(data) - } - } - // DbRo - #[derive(Debug)] - pub struct [<$db_name DbRo>]<B: Backend> { - collections: [<$db_name ColsRo>]<B::Col>, - } - impl<B: Backend> [<$db_name DbRo>]<B> { - pub const NAME: &'static str = stringify!([<$db_name:snake>]); - } - impl<B: Backend> Clone for [<$db_name DbRo>]<B> { - fn clone(&self) -> Self { - [<$db_name DbRo>] { - collections: self.collections.clone(), - } - } - } - // Read operations - pub trait [<$db_name DbReadable>]: Sized { - type Backend: Backend; - - $(fn [<$col_name:snake>](&self) -> &ColRo<<Self::Backend as Backend>::Col, [<$col_name Event>]>;)* - } - impl<B: Backend> [<$db_name DbReadable>] for [<$db_name Db>]<B> { - type Backend = B; - - $(fn [<$col_name:snake>](&self) -> &ColRo<B::Col, [<$col_name Event>]> { &self.collections.[<$col_name:snake>].to_ro() })* - } - impl<B: Backend> [<$db_name DbReadable>] for [<$db_name DbRo>]<B>{ - type Backend = B; - - $(fn [<$col_name:snake>](&self) -> &ColRo<B::Col, [<$col_name Event>]> { &self.collections.[<$col_name:snake>] })* - } - // Write operations - pub trait [<$db_name DbWritable>]: [<$db_name DbReadable>] { - type Backend: Backend; - type Batch; - $(type [<$col_name ColRw>]: DbCollectionRw;)* - type DbRo: Sized; - - fn clear(&self) -> KvResult<()>; - fn get_ro_handler(&self) -> Self::DbRo; - fn open( - backend_conf: <<Self as [<$db_name DbWritable>]>::Backend as kv_typed::backend::Backend>::Conf, - ) -> KvResult <Self>; - fn new_batch(&self) -> Self::Batch; - fn save(&self) -> KvResult<()>; - fn write_batch(&self, batch: Self::Batch) -> KvResult<()>; - $(fn [<$col_name:snake _write>](&self) -> &Self::[<$col_name ColRw>];)* - } - impl<B: Backend> [<$db_name DbWritable>] for [<$db_name Db>]<B> { - type Backend = B; - type Batch = [<$db_name DbBatch>]<B>; - $(type [<$col_name ColRw>] = ColRw<B::Col, [<$col_name Event>]>;)* - type DbRo = [<$db_name DbRo>]<B>; - - #[inline(always)] - fn clear(&self) -> KvResult<()> { - $(self.collections.[<$col_name:snake>].clear()?;)* - Ok(()) - } - #[inline(always)] - fn get_ro_handler(&self) -> Self::DbRo { - [<$db_name DbRo>] { - collections: self.collections.to_ro(), - } - } - #[inline(always)] - fn new_batch(&self) -> Self::Batch { - <[<$db_name DbBatch>]::<B>>::default() - } - fn write_batch(&self, batch: Self::Batch) -> KvResult<()> { - $(self.collections.[<$col_name:snake>].write_batch(batch.[<$col_name:snake>])?;)* - Ok(()) - } - fn open( - backend_conf: <<Self as [<$db_name DbWritable>]>::Backend as kv_typed::backend::Backend>::Conf, - ) -> KvResult <Self> { - let mut db = B::open(&backend_conf)?; - Ok([<$db_name Db>] { - collections: [<$db_name ColsRw>] { - $([<$col_name:snake>]: <ColRw<B::Col, [<$col_name Event>]>>::new( - db.open_col(&backend_conf, $col_path)? - ),)* - }, - }) - } - #[inline(always)] - fn save(&self) -> KvResult<()> { - $(self.collections.[<$col_name:snake>].save()?;)* - Ok(()) - } - $( - #[inline(always)] - fn [<$col_name:snake _write>](&self) -> &ColRw<B::Col, [<$col_name Event>]> { &self.collections.[<$col_name:snake>] } - )* - } - } - } - }; -} diff --git a/rust-libs/tools/kv_typed/src/error.rs b/rust-libs/tools/kv_typed/src/error.rs deleted file mode 100644 index 8762ef816..000000000 --- a/rust-libs/tools/kv_typed/src/error.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed error type - -use crate::*; - -pub type DynErr = Box<dyn Error + Send + Sync + 'static>; - -/// KV Typed error -pub type KvResult<T> = Result<T, KvError>; - -#[allow(type_alias_bounds)] -pub(crate) type BackendResult<BC: BackendCol> = - Result<(<BC as BackendCol>::KeyBytes, <BC as BackendCol>::ValueBytes), DynErr>; - -/// KV Typed error -#[derive(Debug, Error)] -pub enum KvError { - /// Backend error - #[error("Backend error: {0}")] - BackendError(DynErr), - /// Custom - #[error("{0}")] - Custom(DynErr), - // DB corrupted - #[error("DB corrupted:{0}")] - DbCorrupted(String), - // Error at serialisation or deserialisation - #[error("DeserError: {0}")] - DeserError(DynErr), - /// FailToCreateDbFolder - #[error("FailToCreateDbFolder: {0}")] - FailToCreateDbFolder(std::io::Error), - /// FailToSubscribe - #[error("FailToSubscribe")] - FailToSubscribe, -} - -impl From<std::io::Error> for KvError { - fn from(e: std::io::Error) -> Self { - KvError::BackendError(e.into()) - } -} - -#[cfg(feature = "leveldb_backend")] -impl From<crate::backend::leveldb::LevelDbError> for KvError { - fn from(e: crate::backend::leveldb::LevelDbError) -> Self { - KvError::BackendError(Box::new(e).into()) - } -} -#[cfg(feature = "lmdb_backend")] -impl From<lmdb_zero::Error> for KvError { - fn from(e: lmdb_zero::Error) -> Self { - KvError::BackendError(e.into()) - } -} -#[cfg(feature = "sled_backend")] -impl From<sled::Error> for KvError { - fn from(e: sled::Error) -> Self { - KvError::BackendError(Box::new(e).into()) - } -} diff --git a/rust-libs/tools/kv_typed/src/event.rs b/rust-libs/tools/kv_typed/src/event.rs deleted file mode 100644 index 0a2c79abe..000000000 --- a/rust-libs/tools/kv_typed/src/event.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed event - -use crate::*; - -/// Database events -pub type Events<E> = SmallVec<[E; 4]>; - -/// Event trait -pub trait EventTrait: 'static + Debug + PartialEq + Send + Sync { - type K: Key; - type V: Value; - - fn clear() -> Self; - fn upsert(k: Self::K, v: Self::V) -> Self; - fn remove(k: Self::K) -> Self; -} diff --git a/rust-libs/tools/kv_typed/src/explorer.rs b/rust-libs/tools/kv_typed/src/explorer.rs deleted file mode 100644 index e23b2a053..000000000 --- a/rust-libs/tools/kv_typed/src/explorer.rs +++ /dev/null @@ -1,529 +0,0 @@ -use crate::*; -use rayon::{iter::ParallelBridge, prelude::*}; -use std::num::NonZeroUsize; - -pub trait DbExplorable { - fn explore<'a>( - &self, - collection_name: &str, - action: ExplorerAction<'a>, - stringify_json_value: fn(serde_json::Value) -> serde_json::Value, - ) -> KvResult<Result<ExplorerActionResponse, ExplorerActionErr>>; - fn list_collections() -> Vec<(&'static str, &'static str, &'static str)>; -} - -#[derive(Debug, Error)] -#[error("Fail to parse key: {0}")] -pub struct FromExplorerKeyErr(pub DynErr); - -#[derive(Debug, Error)] -#[error("Fail to parse value: {0}")] -pub struct FromExplorerValueErr(pub DynErr); - -pub trait ExplorableKey: Sized { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr>; - fn to_explorer_string(&self) -> KvResult<String>; -} - -impl ExplorableKey for () { - fn from_explorer_str(_: &str) -> Result<Self, FromExplorerKeyErr> { - Ok(()) - } - - fn to_explorer_string(&self) -> KvResult<String> { - Ok(String::with_capacity(0)) - } -} - -impl ExplorableKey for String { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Ok(source.to_owned()) - } - - fn to_explorer_string(&self) -> KvResult<String> { - Ok(self.clone()) - } -} - -macro_rules! impl_explorable_key_for_numbers { - ($($T:ty),*) => {$( - impl ExplorableKey for $T { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - source.parse().map_err(|e| FromExplorerKeyErr(Box::new(e))) - } - - fn to_explorer_string(&self) -> KvResult<String> { - Ok(format!("{}", self)) - } - } - )*}; -} -impl_explorable_key_for_numbers!(usize, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64); - -macro_rules! impl_explorable_key_for_be_numbers { - ($($T:ty),*) => {$( - impl ExplorableKey for $T { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerKeyErr> { - Ok(Self(source.parse().map_err(|e| FromExplorerKeyErr(Box::new(e)))?)) - } - - fn to_explorer_string(&self) -> KvResult<String> { - Ok(format!("{}", self.0)) - } - } - )*}; -} -impl_explorable_key_for_be_numbers!(U32BE, U64BE); - -pub trait ExplorableValue: Sized { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr>; - fn to_explorer_json(&self) -> KvResult<serde_json::Value>; -} - -impl ExplorableValue for () { - fn from_explorer_str(_: &str) -> Result<Self, FromExplorerValueErr> { - Ok(()) - } - - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::String(String::with_capacity(0))) - } -} - -impl ExplorableValue for String { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - Ok(source.to_owned()) - } - - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::String(self.clone())) - } -} - -macro_rules! impl_explorable_value_for_numbers { - ($($T:ty),*) => {$( - impl ExplorableValue for $T { - fn from_explorer_str(source: &str) -> Result<Self, FromExplorerValueErr> { - source.parse().map_err(|e| FromExplorerValueErr(Box::new(e))) - } - - #[allow(trivial_numeric_casts)] - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::Number(serde_json::Number::from_f64(*self as f64).expect("too large number"))) - } - } - )*}; -} - -impl_explorable_value_for_numbers!( - usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64 -); - -impl<T, E> ExplorableValue for Vec<T> -where - T: Display + FromStr<Err = E>, - E: Error + Send + Sync + 'static, -{ - fn from_explorer_str(source: &str) -> Result<Vec<T>, FromExplorerValueErr> { - if let serde_json::Value::Array(json_array) = - serde_json::Value::from_str(source).map_err(|e| FromExplorerValueErr(e.into()))? - { - let mut vec = Vec::with_capacity(json_array.len()); - for value in json_array { - if let serde_json::Value::String(string) = value { - vec.push(<T>::from_str(&string).map_err(|e| FromExplorerValueErr(e.into()))?); - } else { - return Err(FromExplorerValueErr( - format!("Expected array of {}.", stringify!(T)).into(), - )); - } - } - Ok(vec) - } else { - Err(FromExplorerValueErr( - format!("Expected array of {}.", stringify!(T)).into(), - )) - } - } - - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::Array( - self.iter() - .map(|elem| serde_json::Value::String(format!("{}", elem))) - .collect(), - )) - } -} - -macro_rules! impl_explorable_value_for_smallvec { - ($($N:literal),*) => {$( - impl<T, E> ExplorableValue for SmallVec<[T; $N]> - where - T: Display + FromStr<Err = E>, - E: Error + Send + Sync + 'static, - { - fn from_explorer_str(source: &str) -> Result<SmallVec<[T; $N]>, FromExplorerValueErr> { - if let serde_json::Value::Array(json_array) = - serde_json::Value::from_str(source).map_err(|e| FromExplorerValueErr(e.into()))? - { - let mut svec = SmallVec::with_capacity(json_array.len()); - for value in json_array { - if let serde_json::Value::String(string) = value { - svec.push(<T>::from_str(&string).map_err(|e| FromExplorerValueErr(e.into()))?); - } else { - return Err(FromExplorerValueErr(format!("Expected array of {}.", stringify!(T)).into())); - } - } - Ok(svec) - } else { - Err(FromExplorerValueErr(format!("Expected array of {}.", stringify!(T)).into())) - } - } - - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::Array( - self.iter() - .map(|elem| serde_json::Value::String(format!("{}", elem))) - .collect(), - )) - } - } - )*}; -} -impl_explorable_value_for_smallvec!(2, 4, 8, 16, 32, 64); - -impl<T, E> ExplorableValue for BTreeSet<T> -where - T: Display + FromStr<Err = E> + Ord, - E: Error + Send + Sync + 'static, -{ - fn from_explorer_str(source: &str) -> Result<BTreeSet<T>, FromExplorerValueErr> { - if let serde_json::Value::Array(json_array) = - serde_json::Value::from_str(source).map_err(|e| FromExplorerValueErr(e.into()))? - { - let mut bt_set = BTreeSet::new(); - for value in json_array { - if let serde_json::Value::String(string) = value { - bt_set.insert( - <T>::from_str(&string).map_err(|e| FromExplorerValueErr(e.into()))?, - ); - } else { - return Err(FromExplorerValueErr( - format!("Expected array of {}.", stringify!(T)).into(), - )); - } - } - Ok(bt_set) - } else { - Err(FromExplorerValueErr( - format!("Expected array of {}.", stringify!(T)).into(), - )) - } - } - - fn to_explorer_json(&self) -> KvResult<serde_json::Value> { - Ok(serde_json::Value::Array( - self.iter() - .map(|elem| serde_json::Value::String(format!("{}", elem))) - .collect(), - )) - } -} - -#[derive(Debug)] -pub enum ExplorerAction<'a> { - Count, - Get { - key: &'a str, - }, - Find { - key_min: Option<String>, - key_max: Option<String>, - key_regex: Option<regex::Regex>, - value_regex: Option<regex::Regex>, - limit: Option<usize>, - reverse: bool, - step: NonZeroUsize, - }, - Put { - key: &'a str, - value: &'a str, - }, - Delete { - key: &'a str, - }, -} - -#[derive(Debug, PartialEq)] -pub struct EntryFound { - pub key: String, - pub value: serde_json::Value, - pub captures: Option<ValueCaptures>, -} - -#[derive(Debug, PartialEq)] -pub struct ValueCaptures(pub SmallVec<[SmallVec<[Option<String>; 8]>; 8]>); - -#[derive(Debug, PartialEq)] -pub enum ExplorerActionResponse { - Count(usize), - Get(Option<serde_json::Value>), - Find(Vec<EntryFound>), - PutOk, - DeleteOk, -} - -#[derive(Debug, Error)] -#[error("Fail to exec explorer action: {0}")] -pub struct ExplorerActionErr(pub DynErr); -impl From<FromExplorerKeyErr> for ExplorerActionErr { - fn from(e: FromExplorerKeyErr) -> Self { - ExplorerActionErr(e.0) - } -} -impl From<FromExplorerValueErr> for ExplorerActionErr { - fn from(e: FromExplorerValueErr) -> Self { - ExplorerActionErr(e.0) - } -} - -impl<'a> ExplorerAction<'a> { - pub fn exec<BC: BackendCol, E: EventTrait>( - self, - col: &ColRw<BC, E>, - stringify_json_value: fn(serde_json::Value) -> serde_json::Value, - ) -> KvResult<Result<ExplorerActionResponse, ExplorerActionErr>> { - Ok(match self { - Self::Count => Ok(ExplorerActionResponse::Count(col.to_ro().count()?)), - Self::Get { key } => match E::K::from_explorer_str(key) { - Ok(k) => Ok(ExplorerActionResponse::Get( - col.to_ro() - .get(&k)? - .map(|v| v.to_explorer_json()) - .transpose()?, - )), - Err(e) => Err(e.into()), - }, - Self::Find { - key_min, - key_max, - key_regex, - value_regex, - limit, - reverse, - step, - } => match define_range::<E::K>(key_min, key_max) { - Ok(range) => Ok(ExplorerActionResponse::Find(match range { - Range::Full => Self::get_range_inner( - col.to_ro(), - .., - key_regex, - value_regex, - limit, - reverse, - step, - stringify_json_value, - )?, - Range::From(range) => Self::get_range_inner( - col.to_ro(), - range, - key_regex, - value_regex, - limit, - reverse, - step, - stringify_json_value, - )?, - Range::FromTo(range) => Self::get_range_inner( - col.to_ro(), - range, - key_regex, - value_regex, - limit, - reverse, - step, - stringify_json_value, - )?, - Range::To(range) => Self::get_range_inner( - col.to_ro(), - range, - key_regex, - value_regex, - limit, - reverse, - step, - stringify_json_value, - )?, - })), - Err(e) => Err(ExplorerActionErr(e)), - }, - Self::Put { key, value } => match E::K::from_explorer_str(key) { - Ok(k) => match E::V::from_explorer_str(value) { - Ok(v) => { - col.upsert(k, v)?; - Ok(ExplorerActionResponse::PutOk) - } - Err(e) => Err(e.into()), - }, - Err(e) => Err(e.into()), - }, - Self::Delete { key } => match E::K::from_explorer_str(key) { - Ok(k) => { - col.remove(k)?; - Ok(ExplorerActionResponse::DeleteOk) - } - Err(e) => Err(e.into()), - }, - }) - } - #[allow(clippy::too_many_arguments)] - fn get_range_inner<BC: BackendCol, E: EventTrait, R: 'static + RangeBounds<E::K>>( - col: &ColRo<BC, E>, - range: R, - key_regex: Option<regex::Regex>, - value_regex: Option<regex::Regex>, - limit: Option<usize>, - reverse: bool, - step: NonZeroUsize, - stringify_json_value: fn(serde_json::Value) -> serde_json::Value, - ) -> KvResult<Vec<EntryFound>> { - let filter_map_closure = move |entry_res| { - stringify_and_filter_entry_res::<E::K, E::V>( - entry_res, - key_regex.as_ref(), - value_regex.as_ref(), - stringify_json_value, - ) - }; - - if let Some(limit) = limit { - if reverse { - col.iter_rev(range, |iter| { - iter.step_by(step.get()) - .filter_map(filter_map_closure) - .take(limit) - .collect() - }) - } else { - col.iter(range, |iter| { - iter.step_by(step.get()) - .filter_map(filter_map_closure) - .take(limit) - .collect() - }) - } - } else { - { - let (send, recv) = unbounded(); - - let handler = std::thread::spawn(move || { - let iter = recv.into_iter().step_by(step.get()).par_bridge(); - - iter.filter_map(filter_map_closure).collect() - }); - - if reverse { - col.iter_rev(range, |iter| { - for entry_res in iter { - if send.try_send(entry_res).is_err() { - return handler.join().expect("child thread panic"); - } - } - drop(send); - - handler.join().expect("child thread panic") - }) - } else { - col.iter(range, |iter| { - for entry_res in iter { - if send.try_send(entry_res).is_err() { - return handler.join().expect("child thread panic"); - } - } - drop(send); - - handler.join().expect("child thread panic") - }) - } - } - } - } -} - -enum Range<K> { - Full, - From(core::ops::RangeFrom<K>), - To(core::ops::RangeToInclusive<K>), - FromTo(core::ops::RangeInclusive<K>), -} - -fn define_range<K: Key>( - key_min_opt: Option<String>, - key_max_opt: Option<String>, -) -> Result<Range<K>, DynErr> { - if let Some(key_min) = key_min_opt { - let k_min = K::from_explorer_str(&key_min)?; - if let Some(key_max) = key_max_opt { - let k_max = K::from_explorer_str(&key_max)?; - Ok(Range::FromTo(core::ops::RangeInclusive::new(k_min, k_max))) - } else { - Ok(Range::From(core::ops::RangeFrom { start: k_min })) - } - } else if let Some(key_max) = key_max_opt { - let k_max = K::from_explorer_str(&key_max)?; - Ok(Range::To(core::ops::RangeToInclusive { end: k_max })) - } else { - Ok(Range::Full) - } -} - -fn stringify_and_filter_entry_res<K: Key, V: Value>( - entry_res: KvResult<(K, V)>, - key_regex_opt: Option<®ex::Regex>, - value_regex_opt: Option<®ex::Regex>, - stringify_json_value: fn(serde_json::Value) -> serde_json::Value, -) -> Option<KvResult<EntryFound>> { - match entry_res { - Ok((k, v)) => match k.to_explorer_string() { - Ok(key_string) => { - if let Some(key_regex) = key_regex_opt { - if !key_regex.is_match(&key_string) { - return None; - } - } - match v.to_explorer_json() { - Ok(mut value_json) => { - value_json = stringify_json_value(value_json); - let captures = if let Some(value_regex) = value_regex_opt { - let value_string = value_json.to_string(); - if !value_regex.is_match(&value_string) { - return None; - } - Some(ValueCaptures( - value_regex - .captures_iter(&value_string) - .map(|caps| { - caps.iter() - .skip(1) - .map(|m_opt| m_opt.map(|m| m.as_str().to_owned())) - .collect::<SmallVec<[Option<String>; 8]>>() - }) - .collect(), - )) - } else { - None - }; - Some(Ok(EntryFound { - key: key_string, - value: value_json, - captures, - })) - } - Err(e) => Some(Err(e)), - } - } - Err(e) => Some(Err(e)), - }, - Err(e) => Some(Err(e)), - } -} diff --git a/rust-libs/tools/kv_typed/src/from_bytes.rs b/rust-libs/tools/kv_typed/src/from_bytes.rs deleted file mode 100644 index 138f9ff8c..000000000 --- a/rust-libs/tools/kv_typed/src/from_bytes.rs +++ /dev/null @@ -1,127 +0,0 @@ -use crate::*; - -#[derive(Clone, Copy, Debug, Error)] -#[error("Corrupted DB: {0} bytes are wrong aligned or have invalid length")] -pub struct LayoutVerifiedErr(pub &'static str); - -pub trait FromBytes: Sized { - type Err: Error + Send + Sync + 'static; - - /// Create Self from bytes. - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err>; -} - -impl FromBytes for () { - type Err = std::convert::Infallible; - - fn from_bytes(_: &[u8]) -> Result<Self, Self::Err> { - Ok(()) - } -} - -macro_rules! impl_from_bytes_for_numbers { - ($($T:ty),*) => {$( - impl FromBytes for $T { - type Err = std::array::TryFromSliceError; - - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> { - Ok(<$T>::from_le_bytes(bytes.try_into()?)) - } - } - )*}; -} -impl_from_bytes_for_numbers!( - usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64 -); - -macro_rules! impl_from_bytes_for_be_numbers { - ($(($T:ty, $INT:ty)),*) => {$( - impl FromBytes for $T { - type Err = std::array::TryFromSliceError; - - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> { - Ok(Self(<$INT>::from_be_bytes(bytes.try_into()?))) - } - } - )*}; -} -impl_from_bytes_for_be_numbers!((U32BE, u32), (U64BE, u64)); - -impl FromBytes for String { - type Err = std::str::Utf8Error; - - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> { - Ok(std::str::from_utf8(bytes)?.to_owned()) - } -} - -macro_rules! impl_from_bytes_for_smallvec { - ($($N:literal),*) => {$( - impl<T> FromBytes for SmallVec<[T; $N]> - where - T: Copy + zerocopy::FromBytes, - { - type Err = LayoutVerifiedErr; - - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> { - let layout_verified = zerocopy::LayoutVerified::<_, [T]>::new_slice(bytes) - .ok_or_else(|| LayoutVerifiedErr(stringify!(T)).into())?; - Ok(SmallVec::from_slice(layout_verified.into_slice())) - } - } - )*}; -} -impl_from_bytes_for_smallvec!(1, 2, 4, 8, 16, 32, 64); - -impl<T> FromBytes for Vec<T> -where - T: Copy + Default + zerocopy::FromBytes, -{ - type Err = LayoutVerifiedErr; - - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> { - let layout_verified = zerocopy::LayoutVerified::<_, [T]>::new_slice(bytes) - .ok_or(LayoutVerifiedErr(stringify!(Vec<T>)))?; - let slice = layout_verified.into_slice(); - let mut vec = Vec::with_capacity(slice.len()); - vec.resize_with(slice.len(), Default::default); - vec.copy_from_slice(slice); - Ok(vec) - } -} - -impl<T> FromBytes for BTreeSet<T> -where - T: Copy + zerocopy::FromBytes + Ord, -{ - type Err = LayoutVerifiedErr; - - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> { - let layout_verified = zerocopy::LayoutVerified::<_, [T]>::new_slice(bytes) - .ok_or(LayoutVerifiedErr(stringify!(BTreeSet<T>)))?; - let slice = layout_verified.into_slice(); - Ok(slice.iter().copied().collect()) - } -} - -impl<T> FromBytes for HashSet<T> -where - T: Copy + Eq + zerocopy::FromBytes + std::hash::Hash, -{ - type Err = LayoutVerifiedErr; - - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> { - let layout_verified = zerocopy::LayoutVerified::<_, [T]>::new_slice(bytes) - .ok_or(LayoutVerifiedErr(stringify!(HashSet<T>)))?; - let slice = layout_verified.into_slice(); - Ok(slice.iter().copied().collect()) - } -} - -impl FromBytes for IVec { - type Err = std::convert::Infallible; - - fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Err> { - Ok(Self::from(bytes)) - } -} diff --git a/rust-libs/tools/kv_typed/src/iter.rs b/rust-libs/tools/kv_typed/src/iter.rs deleted file mode 100644 index 8671cb182..000000000 --- a/rust-libs/tools/kv_typed/src/iter.rs +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed iterators - -pub mod keys; -pub mod values; - -use crate::*; - -pub trait ReversableIterator: Iterator + Sized { - fn reverse(self) -> Self; - - #[inline(always)] - fn last(self) -> Option<Self::Item> { - self.reverse().next() - } -} - -pub trait ResultIter<T, E>: Iterator<Item = Result<T, E>> + Sized { - #[inline(always)] - fn next_res(&mut self) -> Result<Option<T>, E> { - self.next().transpose() - } -} -impl<I, T, E> ResultIter<T, E> for I where I: Iterator<Item = Result<T, E>> + Sized {} - -pub type RangeBytes = (Bound<IVec>, Bound<IVec>); - -#[derive(Debug)] -pub struct KvIter< - C: BackendCol, - KB: KeyBytes, - VB: ValueBytes, - BI: BackendIter<KB, VB>, - K: Key, - V: Value, -> { - backend_iter: BI, - phantom: PhantomData<(C, KB, VB, K, V)>, -} - -impl<C: BackendCol, KB: KeyBytes, VB: ValueBytes, BI: BackendIter<KB, VB>, K: Key, V: Value> - Iterator for KvIter<C, KB, VB, BI, K, V> -{ - type Item = KvResult<(K, V)>; - - fn next(&mut self) -> Option<Self::Item> { - match self.backend_iter.next() { - Some(Ok((key_bytes, value_bytes))) => match K::from_bytes(key_bytes.as_ref()) { - Ok(key) => match V::from_bytes(value_bytes.as_ref()) { - Ok(value) => Some(Ok((key, value))), - Err(e) => Some(Err(KvError::DeserError(e.into()))), - }, - Err(e) => Some(Err(KvError::DeserError(e.into()))), - }, - Some(Err(e)) => Some(Err(KvError::BackendError(e))), - None => None, - } - } -} - -impl<C: BackendCol, KB: KeyBytes, VB: ValueBytes, BI: BackendIter<KB, VB>, K: Key, V: Value> - KvIter<C, KB, VB, BI, K, V> -{ - pub fn new(backend_iter: BI) -> Self { - Self { - backend_iter, - phantom: PhantomData, - } - } -} - -pub trait EntryIter { - type K: Key; - type V: Value; - type KeysIter: Iterator<Item = KvResult<Self::K>>; - type ValuesIter: Iterator<Item = KvResult<Self::V>>; - - fn keys(self) -> Self::KeysIter; - fn values(self) -> Self::ValuesIter; -} - -impl<C: BackendCol, KB: KeyBytes, VB: ValueBytes, BI: BackendIter<KB, VB>, K: Key, V: Value> - EntryIter for KvIter<C, KB, VB, BI, K, V> -{ - type K = K; - type V = V; - type KeysIter = KvIterKeys<C, KB, VB, BI, K>; - type ValuesIter = KvIterValues<C, KB, VB, BI, K, V>; - - fn keys(self) -> KvIterKeys<C, KB, VB, BI, K> { - KvIterKeys::new(self.backend_iter) - } - fn values(self) -> KvIterValues<C, KB, VB, BI, K, V> { - KvIterValues::new(self.backend_iter) - } -} - -pub(crate) fn convert_range<K: Key, RK: RangeBounds<K>>(range: RK) -> RangeBytes { - let range_start = convert_bound(range.start_bound()); - let range_end = convert_bound(range.end_bound()); - (range_start, range_end) -} - -#[inline(always)] -fn convert_bound<K: Key>(bound_key: Bound<&K>) -> Bound<IVec> { - match bound_key { - Bound::Included(key) => Bound::Included(key.as_bytes(|key_bytes| key_bytes.into())), - Bound::Excluded(key) => Bound::Excluded(key.as_bytes(|key_bytes| key_bytes.into())), - Bound::Unbounded => Bound::Unbounded, - } -} - -#[allow(dead_code, missing_debug_implementations)] -pub struct KvIterRefSlice<'db, BC, D, K, V, F, R> -where - BC: BackendCol, - K: KeyZc, - V: ValueSliceZc, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, -{ - pub(crate) inner: KvInnerIterRefSlice<BC, D, K, V, F>, - pub(crate) reader: OwnedOrRef<'db, R>, -} -impl<'db, BC, D, K, V, F, R> Iterator for KvIterRefSlice<'db, BC, D, K, V, F, R> -where - BC: BackendCol, - K: KeyZc, - V: ValueSliceZc, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, -{ - type Item = KvResult<D>; - - fn next(&mut self) -> Option<Self::Item> { - self.inner.next() - } -} - -#[allow(missing_debug_implementations)] -pub struct KvInnerIterRefSlice<BC, D, K, V, F> -where - BC: BackendCol, - K: KeyZc, - V: ValueSliceZc, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, -{ - pub(crate) backend_iter: BC::Iter, - pub(crate) f: F, - pub(crate) phantom: PhantomData<(D, K, V)>, -} -impl<BC, D, K, V, F> Iterator for KvInnerIterRefSlice<BC, D, K, V, F> -where - BC: BackendCol, - K: KeyZc, - V: ValueSliceZc, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, -{ - type Item = KvResult<D>; - - fn next(&mut self) -> Option<Self::Item> { - match self.backend_iter.next() { - Some(Ok((k_bytes, v_bytes))) => { - if let Some(k_layout) = zerocopy::LayoutVerified::<_, K::Ref>::new(k_bytes.as_ref()) - { - if let Some(v_layout) = zerocopy::LayoutVerified::<_, [V::Elem]>::new_slice( - &v_bytes.as_ref()[V::prefix_len()..], - ) { - Some((self.f)(&k_layout, &v_layout)) - } else { - Some(Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - ))) - } - } else { - Some(Err(KvError::DeserError( - "Bytes are invalid length or alignment.".into(), - ))) - } - } - Some(Err(e)) => Some(Err(KvError::BackendError(e))), - None => None, - } - } -} - -impl<BC, D, K, V, F> ReversableIterator for KvInnerIterRefSlice<BC, D, K, V, F> -where - BC: BackendCol, - K: KeyZc, - V: ValueSliceZc, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, -{ - #[inline(always)] - fn reverse(self) -> Self { - Self { - backend_iter: self.backend_iter.reverse(), - f: self.f, - phantom: PhantomData, - } - } -} diff --git a/rust-libs/tools/kv_typed/src/iter/keys.rs b/rust-libs/tools/kv_typed/src/iter/keys.rs deleted file mode 100644 index 4e2cf10d2..000000000 --- a/rust-libs/tools/kv_typed/src/iter/keys.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed iterators - -use crate::*; - -#[derive(Debug)] -pub struct KvIterKeys<C: BackendCol, KB: KeyBytes, VB: ValueBytes, BI: BackendIter<KB, VB>, K: Key> -{ - backend_iter: BI, - phantom: PhantomData<(C, KB, VB, K)>, -} - -impl<C: BackendCol, KB: KeyBytes, VB: ValueBytes, BI: BackendIter<KB, VB>, K: Key> Iterator - for KvIterKeys<C, KB, VB, BI, K> -{ - type Item = KvResult<K>; - - fn next(&mut self) -> Option<Self::Item> { - match self.backend_iter.next() { - Some(Ok((key_bytes, _value_bytes))) => match K::from_bytes(key_bytes.as_ref()) { - Ok(key) => Some(Ok(key)), - Err(e) => Some(Err(KvError::DeserError(e.into()))), - }, - Some(Err(e)) => Some(Err(KvError::BackendError(e))), - None => None, - } - } -} - -impl<C: BackendCol, KB: KeyBytes, VB: ValueBytes, BI: BackendIter<KB, VB>, K: Key> - KvIterKeys<C, KB, VB, BI, K> -{ - pub(super) fn new(backend_iter: BI) -> Self { - Self { - backend_iter, - phantom: PhantomData, - } - } -} diff --git a/rust-libs/tools/kv_typed/src/iter/values.rs b/rust-libs/tools/kv_typed/src/iter/values.rs deleted file mode 100644 index a96f608df..000000000 --- a/rust-libs/tools/kv_typed/src/iter/values.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed iterators - -use crate::*; - -#[derive(Debug)] -pub struct KvIterValues< - C: BackendCol, - KB: KeyBytes, - VB: ValueBytes, - BI: BackendIter<KB, VB>, - K: Key, - V: Value, -> { - backend_iter: BI, - phantom: PhantomData<(C, KB, VB, K, V)>, -} - -impl<C: BackendCol, KB: KeyBytes, VB: ValueBytes, BI: BackendIter<KB, VB>, K: Key, V: Value> - Iterator for KvIterValues<C, KB, VB, BI, K, V> -{ - type Item = KvResult<V>; - - fn next(&mut self) -> Option<Self::Item> { - match self.backend_iter.next() { - Some(Ok((_key_bytes, value_bytes))) => match V::from_bytes(value_bytes.as_ref()) { - Ok(value) => Some(Ok(value)), - Err(e) => Some(Err(KvError::DeserError(e.into()))), - }, - Some(Err(e)) => Some(Err(KvError::BackendError(e))), - None => None, - } - } -} - -impl<C: BackendCol, KB: KeyBytes, VB: ValueBytes, BI: BackendIter<KB, VB>, K: Key, V: Value> - KvIterValues<C, KB, VB, BI, K, V> -{ - pub(super) fn new(backend_iter: BI) -> Self { - Self { - backend_iter, - phantom: PhantomData, - } - } -} diff --git a/rust-libs/tools/kv_typed/src/key.rs b/rust-libs/tools/kv_typed/src/key.rs deleted file mode 100644 index 72d2bf3cb..000000000 --- a/rust-libs/tools/kv_typed/src/key.rs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed Key trait - -use crate::*; - -/// Trait to be implemented by the collection key - -#[cfg(not(feature = "explorer"))] -pub trait Key: - 'static + AsBytes + Debug + Eq + FromBytes + std::hash::Hash + Send + Sync + Sized -{ -} - -#[cfg(feature = "explorer")] -pub trait Key: - 'static + AsBytes + Debug + Eq + ExplorableKey + FromBytes + std::hash::Hash + Send + Sync + Sized -{ -} - -#[cfg(not(feature = "explorer"))] -impl<T> Key for T where - T: 'static + AsBytes + Debug + Eq + FromBytes + std::hash::Hash + Send + Sync + Sized -{ -} - -#[cfg(feature = "explorer")] -impl<T> Key for T where - T: 'static - + AsBytes - + Debug - + Eq - + ExplorableKey - + FromBytes - + std::hash::Hash - + Send - + Sync - + Sized -{ -} - -pub trait KeyZc: Key { - type Ref: Sized + zerocopy::AsBytes + zerocopy::FromBytes; -} - -impl KeyZc for () { - type Ref = (); -} - -#[derive( - Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, zerocopy::AsBytes, zerocopy::FromBytes, -)] -#[repr(transparent)] -pub struct U32BE(pub u32); - -impl From<&zerocopy::U32<byteorder::BigEndian>> for U32BE { - fn from(u32_zc: &zerocopy::U32<byteorder::BigEndian>) -> Self { - U32BE(u32_zc.get()) - } -} - -impl KeyZc for U32BE { - type Ref = zerocopy::U32<byteorder::BigEndian>; -} - -#[derive( - Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, zerocopy::AsBytes, zerocopy::FromBytes, -)] -#[repr(transparent)] -pub struct U64BE(pub u64); - -impl From<&zerocopy::U64<byteorder::BigEndian>> for U64BE { - fn from(u32_zc: &zerocopy::U64<byteorder::BigEndian>) -> Self { - U64BE(u32_zc.get()) - } -} - -impl KeyZc for U64BE { - type Ref = zerocopy::U64<byteorder::BigEndian>; -} diff --git a/rust-libs/tools/kv_typed/src/lib.rs b/rust-libs/tools/kv_typed/src/lib.rs deleted file mode 100644 index b2487256d..000000000 --- a/rust-libs/tools/kv_typed/src/lib.rs +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Strongly typed key-value storage - -#![allow(clippy::upper_case_acronyms, clippy::from_over_into)] -#![deny( - clippy::unwrap_used, - missing_copy_implementations, - missing_debug_implementations, - trivial_casts, - trivial_numeric_casts, - unstable_features, - unused_import_braces, - unused_qualifications -)] - -mod as_bytes; -pub mod backend; -mod batch; -mod bytes; -mod collection_inner; -mod collection_ro; -mod collection_rw; -mod db_schema; -mod error; -mod event; -#[cfg(feature = "explorer")] -pub mod explorer; -mod from_bytes; -mod iter; -mod key; -mod subscription; -mod transactional_read; -mod transactional_write; -mod utils; -mod value; - -// Re-export dependencies -pub use flume as channel; -#[cfg(feature = "explorer")] -pub use regex; -pub use zerocopy; - -/// Kv Typed prelude -pub mod prelude { - pub use crate::as_bytes::AsBytes; - #[cfg(feature = "leveldb_backend")] - pub use crate::backend::leveldb::{LevelDb, LevelDbConf}; - #[cfg(feature = "lmdb_backend")] - pub use crate::backend::lmdb::{Lmdb, LmdbConf}; - pub use crate::backend::memory::{Mem, MemConf}; - pub use crate::backend::memory_singleton::{MemSingleton, MemSingletonConf}; - #[cfg(feature = "mock")] - pub use crate::backend::mock::{MockBackend, MockBackendCol, MockBackendIter}; - #[cfg(feature = "sled_backend")] - pub use crate::backend::sled::{Config as SledConf, Sled}; - pub use crate::backend::{Backend, BackendCol}; - pub use crate::batch::{Batch, BatchGet}; - #[cfg(feature = "mock")] - pub use crate::collection_ro::MockColRo; - pub use crate::collection_ro::{ - ColRo, DbCollectionRo, DbCollectionRoGetRef, DbCollectionRoGetRefSlice, - DbCollectionRoIterRefSlice, - }; - pub use crate::collection_rw::{ColRw, DbCollectionRw}; - pub use crate::error::{DynErr, KvError, KvResult}; - pub use crate::event::{EventTrait, Events}; - #[cfg(feature = "explorer")] - pub use crate::explorer::{ - ExplorableKey, ExplorableValue, ExplorerActionErr, FromExplorerKeyErr, FromExplorerValueErr, - }; - pub use crate::from_bytes::{FromBytes, LayoutVerifiedErr}; - pub use crate::iter::{ - keys::KvIterKeys, values::KvIterValues, EntryIter, KvIter, KvIterRefSlice, ResultIter, - }; - pub use crate::key::{Key, KeyZc, U32BE, U64BE}; - pub use crate::subscription::{NewSubscribers, Subscriber, Subscribers}; - pub use crate::transactional_read::{TransactionalRead, TxColRo}; - pub use crate::transactional_write::{DbTxCollectionRw, TransactionalWrite, TxColRw}; - pub use crate::utils::arc::Arc; - pub use crate::value::{Value, ValueSliceZc, ValueZc}; - pub use crate::OwnedOrRef; -} - -// Internal crate imports -pub(crate) use crate::backend::{BackendBatch, BackendIter}; -pub(crate) use crate::bytes::{CowKB, CowVB, KeyBytes, ValueBytes}; -pub(crate) use crate::collection_inner::ColInner; -pub(crate) use crate::error::BackendResult; -#[cfg(feature = "explorer")] -pub(crate) use crate::explorer::{ExplorableKey, ExplorableValue}; -pub(crate) use crate::iter::{KvInnerIterRefSlice, RangeBytes, ReversableIterator}; -pub(crate) use crate::prelude::*; -pub(crate) use crate::subscription::{ColSubscribers, SubscriptionsSender}; -pub(crate) use crate::transactional_write::tx_iter::BackendTxIter; -pub(crate) use crate::utils::arc::Arc; -pub(crate) use crate::utils::ivec::IVec; -use flume::{unbounded, Receiver, Sender, TrySendError}; -pub(crate) use smallvec::SmallVec; -pub(crate) use std::{ - collections::{BTreeSet, HashSet}, - convert::TryInto, - error::Error, - fmt::{Debug, Display}, - marker::PhantomData, - ops::{Bound, RangeBounds}, - str::FromStr, -}; -pub(crate) use thiserror::Error; - -pub enum OwnedOrRef<'a, T> { - Owned(T), - Borrow(&'a T), -} -impl<'a, T> AsRef<T> for OwnedOrRef<'a, T> { - fn as_ref(&self) -> &T { - match self { - Self::Owned(t) => t, - Self::Borrow(t) => *t, - } - } -} -impl<'a, T: Debug> Debug for OwnedOrRef<'a, T> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Owned(t) => write!(f, "OwnedOrRef::Owned({:?})", t), - Self::Borrow(t) => write!(f, "OwnedOrRef::Borrow({:?})", t), - } - } -} -impl<'a, T> From<&'a T> for OwnedOrRef<'a, T> { - fn from(borrow: &'a T) -> Self { - Self::Borrow(borrow) - } -} -impl<T> From<T> for OwnedOrRef<'_, T> { - fn from(owned: T) -> Self { - Self::Owned(owned) - } -} diff --git a/rust-libs/tools/kv_typed/src/subscription.rs b/rust-libs/tools/kv_typed/src/subscription.rs deleted file mode 100644 index 049aa446a..000000000 --- a/rust-libs/tools/kv_typed/src/subscription.rs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed subscription - -use crate::*; - -/// Subscriber -pub type Subscriber<E> = Sender<Arc<Events<E>>>; -/// Subscriptions sender -pub(crate) type SubscriptionsSender<E> = Sender<Subscriber<E>>; -/// Subscribers -pub type Subscribers<E> = std::collections::BTreeMap<usize, Subscriber<E>>; -/// New subscribers -pub type NewSubscribers<E> = SmallVec<[Subscriber<E>; 4]>; - -#[derive(Debug)] -#[doc(hidden)] -pub struct ColSubscribers<E: EventTrait> { - subscription_sender: SubscriptionsSender<E>, - subscription_receiver: Receiver<Subscriber<E>>, - subscribers: Subscribers<E>, - subscriber_index: usize, -} - -impl<E: EventTrait> Default for ColSubscribers<E> { - fn default() -> Self { - let (subscription_sender, subscription_receiver) = unbounded(); - ColSubscribers { - subscription_sender, - subscription_receiver, - subscribers: std::collections::BTreeMap::new(), - subscriber_index: 0, - } - } -} - -impl<E: EventTrait> ColSubscribers<E> { - pub(crate) fn get_subscription_sender(&self) -> Sender<Subscriber<E>> { - self.subscription_sender.clone() - } - #[inline(always)] - pub(crate) fn get_new_subscribers(&self) -> NewSubscribers<E> { - if !self.subscription_receiver.is_empty() { - let mut new_subscribers = SmallVec::new(); - while let Ok(subscriber) = self.subscription_receiver.try_recv() { - new_subscribers.push(subscriber) - } - new_subscribers - } else { - SmallVec::new() - } - } - pub(crate) fn notify_subscribers(&self, events: Arc<Events<E>>) -> Vec<usize> { - let mut died_subscribers = Vec::with_capacity(self.subscribers.len()); - let mut unsend_events_opt = None; - for (id, subscriber) in &self.subscribers { - if let Err(e) = subscriber.try_send( - unsend_events_opt - .take() - .unwrap_or_else(|| Arc::clone(&events)), - ) { - match e { - TrySendError::Disconnected(events_) => { - unsend_events_opt = Some(events_); - died_subscribers.push(*id); - } - TrySendError::Full(events_) => { - unsend_events_opt = Some(events_); - } - } - } - } - died_subscribers - } - #[inline(always)] - pub(crate) fn add_new_subscribers(&mut self) { - for new_subscriber in self.get_new_subscribers() { - self.subscribers - .insert(self.subscriber_index, new_subscriber); - self.subscriber_index += 1; - } - } - #[inline(always)] - pub(crate) fn prune_subscribers(&mut self, died_subscribers: Vec<usize>) { - for died_subscriber in died_subscribers { - self.subscribers.remove(&died_subscriber); - } - } -} diff --git a/rust-libs/tools/kv_typed/src/transactional_read.rs b/rust-libs/tools/kv_typed/src/transactional_read.rs deleted file mode 100644 index 647861f9b..000000000 --- a/rust-libs/tools/kv_typed/src/transactional_read.rs +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed transactional read - -use crate::*; -use parking_lot::RwLockReadGuard as ReadGuard; - -type TxColRoReader<'r, BC, E> = parking_lot::RwLockReadGuard<'r, ColInner<BC, E>>; - -pub struct TxColRo<'tx, BC: BackendCol, E: EventTrait> { - col_reader: ReadGuard<'tx, ColInner<BC, E>>, -} -impl<'tx, BC: BackendCol, E: EventTrait> Debug for TxColRo<'tx, BC, E> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("LevelDbCol") - .field("col_reader", &format!("{:?}", self.col_reader)) - .finish() - } -} -impl<'tx, BC: BackendCol, E: EventTrait> TxColRo<'tx, BC, E> { - #[inline(always)] - fn new(col_reader: ReadGuard<'tx, ColInner<BC, E>>) -> Self { - TxColRo { col_reader } - } - #[inline(always)] - pub fn count(&self) -> KvResult<usize> { - self.col_reader.backend_col.count() - } - #[inline(always)] - pub fn get(&self, k: &E::K) -> KvResult<Option<E::V>> { - self.col_reader.backend_col.get(k) - } - #[allow(clippy::type_complexity)] - #[inline(always)] - /// Don't worry about complex iter type. Use it like an `impl Iterator<Item=KvResult<(K, V)>>`. - pub fn iter<D, R, F>(&self, range: R, f: F) -> D - where - D: Send + Sync, - R: 'static + RangeBounds<E::K>, - F: FnOnce(KvIter<BC, BC::KeyBytes, BC::ValueBytes, BC::Iter, E::K, E::V>) -> D, - { - let range_bytes = crate::iter::convert_range::<E::K, R>(range); - let backend_iter = self.col_reader.backend_col.iter::<E::K, E::V>(range_bytes); - f(KvIter::new(backend_iter)) - } - #[allow(clippy::type_complexity)] - #[inline(always)] - /// Don't worry about complex iter type. Use it like an `impl Iterator<Item=KvResult<(K, V)>>`. - pub fn iter_rev<D, R, F>(&self, range: R, f: F) -> D - where - D: Send + Sync, - R: 'static + RangeBounds<E::K>, - F: FnOnce(KvIter<BC, BC::KeyBytes, BC::ValueBytes, BC::Iter, E::K, E::V>) -> D, - { - let range_bytes = crate::iter::convert_range::<E::K, R>(range); - let backend_iter = self - .col_reader - .backend_col - .iter::<E::K, E::V>(range_bytes) - .reverse(); - f(KvIter::new(backend_iter)) - } -} -impl<'tx, V: ValueZc, BC: BackendCol, E: EventTrait<V = V>> TxColRo<'tx, BC, E> { - pub fn get_ref<D, F: Fn(&V::Ref) -> KvResult<D>>(&self, k: &E::K, f: F) -> KvResult<Option<D>> { - self.col_reader.backend_col.get_ref::<E::K, V, D, F>(k, f) - } -} -impl<'tx, K: KeyZc, V: ValueSliceZc, BC: BackendCol, E: EventTrait<K = K, V = V>> - TxColRo<'tx, BC, E> -{ - pub fn iter_ref_slice<D, R, F>( - &self, - range: R, - f: F, - ) -> KvIterRefSlice<BC, D, K, V, F, TxColRoReader<BC, E>> - where - K: KeyZc, - V: ValueSliceZc, - R: 'static + RangeBounds<K>, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, - { - let range: RangeBytes = crate::iter::convert_range::<K, R>(range); - let inner_iter = self - .col_reader - .backend_col - .iter_ref_slice::<D, K, V, F>(range, f); - - KvIterRefSlice { - inner: inner_iter, - reader: OwnedOrRef::Borrow(&self.col_reader), - } - } - pub fn iter_ref_slice_rev<D, R, F>( - &self, - range: R, - f: F, - ) -> KvIterRefSlice<BC, D, K, V, F, TxColRoReader<BC, E>> - where - K: KeyZc, - V: ValueSliceZc, - R: 'static + RangeBounds<K>, - F: FnMut(&K::Ref, &[V::Elem]) -> KvResult<D>, - { - let range: RangeBytes = crate::iter::convert_range::<K, R>(range); - let inner_iter = self - .col_reader - .backend_col - .iter_ref_slice::<D, K, V, F>(range, f) - .reverse(); - - KvIterRefSlice { - inner: inner_iter, - reader: OwnedOrRef::Borrow(&self.col_reader), - } - } -} - -impl<'tx, V: ValueSliceZc, BC: BackendCol, E: EventTrait<V = V>> TxColRo<'tx, BC, E> { - pub fn get_ref_slice<D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &E::K, - f: F, - ) -> KvResult<Option<D>> { - self.col_reader - .backend_col - .get_ref_slice::<E::K, V, D, F>(k, f) - } -} - -pub trait TransactionalRead<'tx, BC: BackendCol> { - type TxCols; - - fn read<D, F: Fn(Self::TxCols) -> KvResult<D>>(&'tx self, f: F) -> KvResult<D>; - - fn try_read<D, F: Fn(Self::TxCols) -> KvResult<D>>(&'tx self, f: F) -> Result<KvResult<D>, F>; -} - -impl<'tx, BC: BackendCol, E: EventTrait> TransactionalRead<'tx, BC> for &'tx ColRo<BC, E> { - type TxCols = TxColRo<'tx, BC, E>; - - fn read<D, F: Fn(Self::TxCols) -> KvResult<D>>(&'tx self, f: F) -> KvResult<D> { - let read_guard_0 = self.inner.read(); - - f(TxColRo::new(read_guard_0)) - } - - fn try_read<D, F: Fn(Self::TxCols) -> KvResult<D>>(&'tx self, f: F) -> Result<KvResult<D>, F> { - if let Some(read_guard_0) = self.inner.try_read() { - Ok(f(TxColRo::new(read_guard_0))) - } else { - Err(f) - } - } -} - -macro_rules! impl_transactional_read { - ($($i:literal),*) => { - paste::paste! { - impl<'tx, BC: BackendCol $( ,[<E $i>]: EventTrait)*> TransactionalRead<'tx, BC> - for ($(&'tx ColRo<BC, [<E $i>]>, )*) - { - type TxCols = ($(TxColRo<'tx, BC, [<E $i>]>, )*); - - fn read<D, F: Fn(Self::TxCols) -> KvResult<D>>( - &'tx self, - f: F, - ) -> KvResult<D> { - $(let [<read_guard_ $i>] = self.$i.inner.read();)* - - f(($(TxColRo::new([<read_guard_ $i>]), )*)) - } - - fn try_read<D, F: Fn(Self::TxCols) -> KvResult<D>>( - &'tx self, - f: F, - ) -> Result<KvResult<D>, F> { - $(let [<read_guard_opt_ $i>] = self.$i.inner.try_read();)* - - if $([<read_guard_opt_ $i>].is_none() || )* false { - Err(f) - } else { - Ok(f(($(TxColRo::new([<read_guard_opt_ $i>].expect("unreachable")), )*))) - } - } - } - } - }; -} -impl_transactional_read!(0, 1); -impl_transactional_read!(0, 1, 2); -impl_transactional_read!(0, 1, 2, 3); -impl_transactional_read!(0, 1, 2, 3, 4); -impl_transactional_read!(0, 1, 2, 3, 4, 5); -impl_transactional_read!(0, 1, 2, 3, 4, 5, 6); -impl_transactional_read!(0, 1, 2, 3, 4, 5, 6, 7); -impl_transactional_read!(0, 1, 2, 3, 4, 5, 6, 7, 8); -impl_transactional_read!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); diff --git a/rust-libs/tools/kv_typed/src/transactional_write.rs b/rust-libs/tools/kv_typed/src/transactional_write.rs deleted file mode 100644 index 2595e6302..000000000 --- a/rust-libs/tools/kv_typed/src/transactional_write.rs +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed transactional write - -pub(crate) mod tx_iter; - -use crate::*; -use parking_lot::RwLockUpgradableReadGuard as UpgradableReadGuard; - -pub struct TxColRw<'tx, BC: BackendCol, E: EventTrait> { - batch: &'static mut Batch<BC, ColRw<BC, E>>, - col_reader: &'tx UpgradableReadGuard<'tx, ColInner<BC, E>>, -} - -impl<'tx, BC: BackendCol, E: EventTrait> TxColRw<'tx, BC, E> { - #[doc(hidden)] - /// For internal usage only MUST NOT USE - pub fn new( - batch: &mut Batch<BC, ColRw<BC, E>>, - upgradable_guard: &UpgradableReadGuard<ColInner<BC, E>>, - ) -> Self { - TxColRw { - batch: unsafe { std::mem::transmute(batch) }, - col_reader: unsafe { std::mem::transmute(upgradable_guard) }, - } - } -} - -impl<'tx, BC: BackendCol, E: EventTrait> Debug for TxColRw<'tx, BC, E> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("LevelDbCol") - .field("batch", &format!("{:?}", self.batch)) - .field("col_reader", &format!("{:?}", self.col_reader)) - .finish() - } -} - -impl<'tx, V: ValueZc, BC: BackendCol, E: EventTrait<V = V>> TxColRw<'tx, BC, E> { - pub fn get_ref<D, F: Fn(&V::Ref) -> KvResult<D>>(&self, k: &E::K, f: F) -> KvResult<Option<D>> { - self.col_reader.backend_col.get_ref::<E::K, V, D, F>(k, f) - } -} -impl<'tx, V: ValueSliceZc, BC: BackendCol, E: EventTrait<V = V>> TxColRw<'tx, BC, E> { - pub fn get_ref_slice<D, F: Fn(&[V::Elem]) -> KvResult<D>>( - &self, - k: &E::K, - f: F, - ) -> KvResult<Option<D>> { - self.col_reader - .backend_col - .get_ref_slice::<E::K, V, D, F>(k, f) - } -} - -impl<'tx, BC: BackendCol, E: EventTrait> TxColRw<'tx, BC, E> { - #[inline(always)] - pub fn count(&self) -> KvResult<usize> { - self.col_reader.backend_col.count() - } - #[inline(always)] - pub fn get(&self, k: &E::K) -> KvResult<Option<E::V>> { - match self.batch.get(k) { - batch::BatchGet::None => self.col_reader.backend_col.get(k), - batch::BatchGet::Deleted => Ok(None), - batch::BatchGet::Updated(v) => Ok(Some(v.as_bytes(|v_bytes| { - E::V::from_bytes(v_bytes).map_err(|e| KvError::DeserError(e.into())) - })?)), - } - } - #[allow(clippy::type_complexity)] - #[inline(always)] - /// Don't worry about complex iter type. Use it like an `impl Iterator<Item=KvResult<(K, V)>>`. - pub fn iter<D, R, F>(&'tx self, range: R, f: F) -> D - where - D: Send + Sync, - R: 'static + RangeBounds<E::K>, - F: FnOnce( - KvIter< - BC, - CowKB<'tx, BC::KeyBytes>, - CowVB<'tx, BC::ValueBytes>, - BackendTxIter<BC>, - E::K, - E::V, - >, - ) -> D, - { - let range_bytes = crate::iter::convert_range::<E::K, R>(range); - let backend_iter = self.col_reader.backend_col.iter::<E::K, E::V>(range_bytes); - f(KvIter::new(BackendTxIter::new( - backend_iter, - &self.batch.tree, - ))) - } - #[allow(clippy::type_complexity)] - #[inline(always)] - /// Don't worry about complex iter type. Use it like an `impl Iterator<Item=KvResult<(K, V)>>`. - pub fn iter_rev<D, R, F>(&'tx self, range: R, f: F) -> D - where - D: Send + Sync, - R: 'static + RangeBounds<E::K>, - F: FnOnce( - KvIter< - BC, - CowKB<'tx, BC::KeyBytes>, - CowVB<'tx, BC::ValueBytes>, - BackendTxIter<BC>, - E::K, - E::V, - >, - ) -> D, - { - let range_bytes = crate::iter::convert_range::<E::K, R>(range); - let backend_iter = self.col_reader.backend_col.iter::<E::K, E::V>(range_bytes); - f(KvIter::new( - BackendTxIter::new(backend_iter, &self.batch.tree).reverse(), - )) - } -} - -pub trait DbTxCollectionRw { - type K: Key; - type V: Value; - type Event: EventTrait<K = Self::K, V = Self::V>; - - fn remove(&mut self, k: Self::K); - fn upsert(&mut self, k: Self::K, v: Self::V); -} - -impl<'tx, BC: BackendCol, E: EventTrait> DbTxCollectionRw for TxColRw<'tx, BC, E> { - type K = E::K; - type V = E::V; - type Event = E; - - #[inline(always)] - fn remove(&mut self, k: Self::K) { - self.batch.remove(k) - } - #[inline(always)] - fn upsert(&mut self, k: Self::K, v: Self::V) { - self.batch.upsert(k, v) - } -} - -pub trait TransactionalWrite<'tx, BC: BackendCol> { - type TxCols; - - fn write<D, F: FnOnce(Self::TxCols) -> KvResult<D>>(&'tx self, f: F) -> KvResult<D>; -} - -impl<'tx, BC: BackendCol, E: EventTrait> TransactionalWrite<'tx, BC> for &'tx ColRw<BC, E> { - type TxCols = TxColRw<'tx, BC, E>; - - fn write<D, F: FnOnce(Self::TxCols) -> KvResult<D>>(&'tx self, f: F) -> KvResult<D> { - let upgradable_guard = self.inner.inner.upgradable_read(); - - let mut batch = Batch::<BC, ColRw<BC, E>>::default(); - - let tx_col = TxColRw { - batch: unsafe { std::mem::transmute(&mut batch) }, - col_reader: unsafe { std::mem::transmute(&upgradable_guard) }, - }; - let data = f(tx_col)?; - - // Prepare commit - let (backend_batch, events) = batch.into_backend_batch_and_events(); - - // Acquire exclusive lock - let mut write_guard = UpgradableReadGuard::upgrade(upgradable_guard); - - // Commit - self.write_backend_batch(backend_batch, events, &mut write_guard)?; - - Ok(data) - } -} - -macro_rules! impl_transactional_write { - ($($i:literal),*) => { - paste::paste! { - impl<'tx, BC: BackendCol $( ,[<E $i>]: EventTrait)*> TransactionalWrite<'tx, BC> - for ($(&'tx ColRw<BC, [<E $i>]>, )*) - { - type TxCols = ($(TxColRw<'tx, BC, [<E $i>]>, )*); - - fn write<D, F: FnOnce(Self::TxCols) -> KvResult<D>>( - &'tx self, - f: F, - ) -> KvResult<D> { - $(let [<upgradable_guard_ $i>] = self.$i.inner.inner.upgradable_read();)* - - $(let mut [<batch_ $i>] = Batch::<BC, ColRw<BC, [<E $i>]>>::default();)* - - $(let [<tx_col $i>] = TxColRw { - batch: unsafe { std::mem::transmute(&mut [<batch_ $i>]) }, - col_reader: unsafe { std::mem::transmute(&[<upgradable_guard_ $i>]) }, - };)* - - let data = f(($([<tx_col $i>], )*))?; - - // Prepare commit - $(let ([<backend_batch_ $i>], [<events_ $i>]) = [<batch_ $i>].into_backend_batch_and_events();)* - - // Acquire exclusive lock - $(let mut [<write_guard_ $i>] = UpgradableReadGuard::upgrade([<upgradable_guard_ $i>]);)* - - // Commit - $(self.$i.write_backend_batch([<backend_batch_ $i>], [<events_ $i>], &mut [<write_guard_ $i>])?;)* - - Ok(data) - } - } - } - }; -} -impl_transactional_write!(0, 1); -impl_transactional_write!(0, 1, 2); -impl_transactional_write!(0, 1, 2, 3); -impl_transactional_write!(0, 1, 2, 3, 4); -impl_transactional_write!(0, 1, 2, 3, 4, 5); -impl_transactional_write!(0, 1, 2, 3, 4, 5, 6); -impl_transactional_write!(0, 1, 2, 3, 4, 5, 6, 7); -impl_transactional_write!(0, 1, 2, 3, 4, 5, 6, 7, 8); -impl_transactional_write!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); diff --git a/rust-libs/tools/kv_typed/src/transactional_write/tx_iter.rs b/rust-libs/tools/kv_typed/src/transactional_write/tx_iter.rs deleted file mode 100644 index fe1c28bcf..000000000 --- a/rust-libs/tools/kv_typed/src/transactional_write/tx_iter.rs +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed transactional iterator - -use crate::*; -use std::collections::BTreeMap; - -#[doc(hidden)] -#[derive(Debug)] -pub struct BackendTxIter<'b, BC: BackendCol> { - batch_end_reached: bool, - batch_iter: std::collections::btree_map::Iter<'b, IVec, Option<IVec>>, - batch_tree_ref: &'b BTreeMap<IVec, Option<IVec>>, - backend_iter: BC::Iter, - db_end_reached: bool, - next_batch_entry_opt: Option<(&'b IVec, &'b Option<IVec>)>, - next_db_entry_opt: Option<(BC::KeyBytes, BC::ValueBytes)>, - reverted: bool, -} - -impl<'b, BC: BackendCol> BackendTxIter<'b, BC> { - pub(crate) fn new( - backend_iter: BC::Iter, - batch_tree: &'b BTreeMap<IVec, Option<IVec>>, - ) -> Self { - Self { - batch_end_reached: false, - batch_iter: batch_tree.iter(), - batch_tree_ref: batch_tree, - backend_iter, - db_end_reached: false, - next_batch_entry_opt: None, - next_db_entry_opt: None, - reverted: false, - } - } -} - -impl<'b, BC: BackendCol> BackendTxIter<'b, BC> { - fn get_next_db_item(&mut self) -> Option<BackendResult<BC>> { - match self.backend_iter.next() { - Some(Ok(entry)) => { - if self.batch_tree_ref.contains_key(entry.0.as_ref()) { - self.get_next_db_item() - } else { - Some(Ok(entry)) - } - } - o => o, - } - } -} - -#[allow(type_alias_bounds)] -type CowBytesEntry<'a, BC: BackendCol> = (CowKB<'a, BC::KeyBytes>, CowVB<'a, BC::ValueBytes>); - -impl<'b, BC: BackendCol> Iterator for BackendTxIter<'b, BC> { - type Item = Result<CowBytesEntry<'b, BC>, DynErr>; - - fn next(&mut self) -> Option<Self::Item> { - if self.next_batch_entry_opt.is_none() { - self.next_batch_entry_opt = if self.reverted { - self.batch_iter.next_back() - } else { - self.batch_iter.next() - }; - } - if self.next_batch_entry_opt.is_none() { - self.batch_end_reached = true; - } - if self.next_db_entry_opt.is_none() { - self.next_db_entry_opt = match self.get_next_db_item() { - Some(Ok(entry)) => Some(entry), - Some(Err(e)) => return Some(Err(e)), - None => { - self.db_end_reached = true; - None - } - }; - } - - if self.batch_end_reached { - if self.db_end_reached { - None - } else { - // Return db item - Some(Ok(self - .next_db_entry_opt - .take() - .map(|(k, v)| (CowKB::O(k), CowVB::O(v))) - .expect("unreachable"))) - } - } else if self.db_end_reached { - // Return batch item - if let Some((k, v_opt)) = self.next_batch_entry_opt.take() { - if let Some(v) = v_opt { - Some(Ok((CowKB::B(k.as_ref()), CowVB::B(v.as_ref())))) - } else { - self.next() - } - } else { - // batch_end_reached = false - unreachable!() - } - } else if let Some((k_batch, v_batch_opt)) = self.next_batch_entry_opt.take() { - if let Some((k_db, v_db)) = self.next_db_entry_opt.take() { - if (!self.reverted && k_batch.as_ref() <= k_db.as_ref()) - || (self.reverted && k_batch.as_ref() >= k_db.as_ref()) - { - self.next_db_entry_opt = Some((k_db, v_db)); - // Return batch item - if let Some(v_batch) = v_batch_opt { - Some(Ok((CowKB::B(k_batch.as_ref()), CowVB::B(v_batch.as_ref())))) - } else { - self.next() - } - } else { - self.next_batch_entry_opt = Some((k_batch, v_batch_opt)); - // Return db item - Some(Ok((CowKB::O(k_db), CowVB::O(v_db)))) - } - } else { - // db_end_reached = false - unreachable!() - } - } else { - // batch_end_reached = false - unreachable!() - } - } -} - -impl<'b, BC: BackendCol> ReversableIterator for BackendTxIter<'b, BC> { - fn reverse(mut self) -> Self { - self.backend_iter = self.backend_iter.reverse(); - self.reverted = true; - self - } -} - -impl<'b, BC: BackendCol> BackendIter<CowKB<'b, BC::KeyBytes>, CowVB<'b, BC::ValueBytes>> - for BackendTxIter<'b, BC> -{ -} diff --git a/rust-libs/tools/kv_typed/src/utils.rs b/rust-libs/tools/kv_typed/src/utils.rs deleted file mode 100644 index 68bd74c49..000000000 --- a/rust-libs/tools/kv_typed/src/utils.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed utils - -pub mod arc; -#[cfg(not(feature = "sled_backend"))] -pub mod ivec; -#[cfg(feature = "sled_backend")] -pub mod ivec { - pub use sled::IVec; -} diff --git a/rust-libs/tools/kv_typed/src/utils/arc.rs b/rust-libs/tools/kv_typed/src/utils/arc.rs deleted file mode 100644 index 74a7b5856..000000000 --- a/rust-libs/tools/kv_typed/src/utils/arc.rs +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV typed Arc - -#![allow(clippy::unwrap_used, dead_code, unsafe_code)] -/// We use this because we never use the weak count on the std -/// `Arc`, but we use a LOT of `Arc`'s, so the extra 8 bytes -/// turn into a huge overhead. -use std::{ - alloc::{alloc, dealloc, Layout}, - convert::TryFrom, - fmt::{self, Debug}, - mem, - ops::Deref, - ptr, - sync::atomic::{AtomicUsize, Ordering}, -}; - -// we make this repr(C) because we do a raw -// write to the beginning where we expect -// the rc to be. -#[repr(C)] -struct ArcInner<T: ?Sized> { - rc: AtomicUsize, - inner: T, -} - -pub struct Arc<T: ?Sized> { - ptr: *mut ArcInner<T>, -} - -unsafe impl<T: Send + Sync + ?Sized> Send for Arc<T> {} -unsafe impl<T: Send + Sync + ?Sized> Sync for Arc<T> {} - -impl<T: Debug + ?Sized> Debug for Arc<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - Debug::fmt(&**self, f) - } -} - -impl<T> Arc<T> { - pub fn new(inner: T) -> Arc<T> { - let bx = Box::new(ArcInner { - inner, - rc: AtomicUsize::new(1), - }); - let ptr = Box::into_raw(bx); - Arc { ptr } - } - - // See std::sync::arc::Arc::copy_from_slice, - // "Unsafe because the caller must either take ownership or bind `T: Copy`" - unsafe fn copy_from_slice(s: &[T]) -> Arc<[T]> { - let align = std::cmp::max(mem::align_of::<T>(), mem::align_of::<AtomicUsize>()); - - let rc_width = std::cmp::max(align, mem::size_of::<AtomicUsize>()); - let data_width = mem::size_of::<T>().checked_mul(s.len()).unwrap(); - - let size_unpadded = rc_width.checked_add(data_width).unwrap(); - // Pad size out to alignment - let size_padded = (size_unpadded + align - 1) & !(align - 1); - - let layout = Layout::from_size_align(size_padded, align).unwrap(); - - let ptr = alloc(layout); - - assert!(!ptr.is_null(), "failed to allocate Arc"); - #[allow(clippy::cast_ptr_alignment)] - ptr::write(ptr as _, AtomicUsize::new(1)); - - let data_ptr = ptr.add(rc_width); - ptr::copy_nonoverlapping(s.as_ptr(), data_ptr as _, s.len()); - - let fat_ptr: *const ArcInner<[T]> = Arc::fatten(ptr, s.len()); - - Arc { - ptr: fat_ptr as *mut _, - } - } - - /// <https://users.rust-lang.org/t/construct-fat-pointer-to-struct/29198/9> - #[allow(trivial_casts)] - fn fatten(data: *const u8, len: usize) -> *const ArcInner<[T]> { - // Requirements of slice::from_raw_parts. - assert!(!data.is_null()); - assert!(isize::try_from(len).is_ok()); - - let slice = unsafe { core::slice::from_raw_parts(data as *const (), len) }; - slice as *const [()] as *const _ - } - - pub fn into_raw(arc: Arc<T>) -> *const T { - let ptr = unsafe { &(*arc.ptr).inner }; - #[allow(clippy::mem_forget)] - mem::forget(arc); - ptr - } - - #[allow(clippy::missing_safety_doc)] - pub unsafe fn from_raw(ptr: *const T) -> Arc<T> { - let align = std::cmp::max(mem::align_of::<T>(), mem::align_of::<AtomicUsize>()); - - let rc_width = std::cmp::max(align, mem::size_of::<AtomicUsize>()); - - let sub_ptr = (ptr as *const u8).sub(rc_width) as *mut ArcInner<T>; - - Arc { ptr: sub_ptr } - } -} - -impl<T: ?Sized> Arc<T> { - pub fn strong_count(arc: &Arc<T>) -> usize { - unsafe { (*arc.ptr).rc.load(Ordering::Acquire) } - } - - pub fn get_mut(arc: &mut Arc<T>) -> Option<&mut T> { - if Arc::strong_count(arc) == 1 { - Some(unsafe { &mut arc.ptr.as_mut().unwrap().inner }) - } else { - None - } - } -} - -impl<T: ?Sized + Clone> Arc<T> { - pub fn make_mut(arc: &mut Arc<T>) -> &mut T { - if Arc::strong_count(arc) != 1 { - *arc = Arc::new((**arc).clone()); - assert_eq!(Arc::strong_count(arc), 1); - } - Arc::get_mut(arc).unwrap() - } -} - -impl<T: Default> Default for Arc<T> { - fn default() -> Arc<T> { - Arc::new(T::default()) - } -} - -impl<T: ?Sized> Clone for Arc<T> { - fn clone(&self) -> Arc<T> { - // safe to use Relaxed ordering below because - // of the required synchronization for passing - // any objects to another thread. - let last_count = unsafe { (*self.ptr).rc.fetch_add(1, Ordering::Relaxed) }; - - if last_count == usize::max_value() { - std::process::abort(); - } - - Arc { ptr: self.ptr } - } -} - -impl<T: ?Sized> Drop for Arc<T> { - fn drop(&mut self) { - unsafe { - let rc = (*self.ptr).rc.fetch_sub(1, Ordering::Release) - 1; - if rc == 0 { - std::sync::atomic::fence(Ordering::Acquire); - Box::from_raw(self.ptr); - } - } - } -} - -impl<T: Copy> From<&[T]> for Arc<[T]> { - #[inline] - fn from(s: &[T]) -> Arc<[T]> { - unsafe { Arc::copy_from_slice(s) } - } -} - -#[allow(clippy::fallible_impl_from)] -impl<T> From<Box<[T]>> for Arc<[T]> { - #[inline] - fn from(b: Box<[T]>) -> Arc<[T]> { - let len = b.len(); - unsafe { - let src = Box::into_raw(b); - let value_layout = Layout::for_value(&*src); - let align = std::cmp::max(value_layout.align(), mem::align_of::<AtomicUsize>()); - let rc_width = std::cmp::max(align, mem::size_of::<AtomicUsize>()); - let unpadded_size = rc_width.checked_add(value_layout.size()).unwrap(); - // pad the total `Arc` allocation size to the alignment of - // `max(value, AtomicUsize)` - let size = (unpadded_size + align - 1) & !(align - 1); - let dst_layout = Layout::from_size_align(size, align).unwrap(); - let dst = alloc(dst_layout); - assert!(!dst.is_null(), "failed to allocate Arc"); - - #[allow(clippy::cast_ptr_alignment)] - ptr::write(dst as _, AtomicUsize::new(1)); - let data_ptr = dst.add(rc_width); - ptr::copy_nonoverlapping(src as *const u8, data_ptr, value_layout.size()); - - // free the old box memory without running Drop - if value_layout.size() != 0 { - dealloc(src as *mut u8, value_layout); - } - - let fat_ptr: *const ArcInner<[T]> = Arc::fatten(dst, len); - - Arc { - ptr: fat_ptr as *mut _, - } - } - } -} - -#[test] -fn boxed_slice_to_arc_slice() { - let box1: Box<[u8]> = Box::new([1, 2, 3]); - let arc1: Arc<[u8]> = box1.into(); - assert_eq!(&*arc1, &*vec![1, 2, 3]); - let box2: Box<[u64]> = Box::new([1, 2, 3]); - let arc2: Arc<[u64]> = box2.into(); - assert_eq!(&*arc2, &*vec![1, 2, 3]); -} - -impl<T> From<Vec<T>> for Arc<[T]> { - #[inline] - fn from(mut v: Vec<T>) -> Arc<[T]> { - unsafe { - let arc = Arc::copy_from_slice(&v); - - // Allow the Vec to free its memory, but not destroy its contents - v.set_len(0); - - arc - } - } -} - -impl<T: ?Sized> Deref for Arc<T> { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &(*self.ptr).inner } - } -} - -impl<T: ?Sized> std::borrow::Borrow<T> for Arc<T> { - fn borrow(&self) -> &T { - &**self - } -} - -impl<T: ?Sized> AsRef<T> for Arc<T> { - fn as_ref(&self) -> &T { - &**self - } -} diff --git a/rust-libs/tools/kv_typed/src/utils/ivec.rs b/rust-libs/tools/kv_typed/src/utils/ivec.rs deleted file mode 100644 index 50a8d7528..000000000 --- a/rust-libs/tools/kv_typed/src/utils/ivec.rs +++ /dev/null @@ -1,314 +0,0 @@ -use std::{ - convert::TryFrom, - fmt, - hash::{Hash, Hasher}, - ops::{Deref, DerefMut}, - sync::Arc, -}; - -const CUTOFF: usize = 22; - -type Inner = [u8; CUTOFF]; - -/// A buffer that may either be inline or remote and protected -/// by an Arc -#[derive(Clone)] -pub struct IVec(IVecInner); - -impl Default for IVec { - fn default() -> Self { - Self::from(&[]) - } -} - -impl Hash for IVec { - fn hash<H: Hasher>(&self, state: &mut H) { - self.deref().hash(state); - } -} - -#[derive(Clone)] -enum IVecInner { - Inline(u8, Inner), - Remote(Arc<[u8]>), - Subslice { - base: Arc<[u8]>, - offset: usize, - len: usize, - }, -} - -const fn is_inline_candidate(length: usize) -> bool { - length <= CUTOFF -} - -impl IVec { - pub fn subslice(&self, slice_offset: usize, len: usize) -> Self { - assert!(self.len().checked_sub(slice_offset).expect("") >= len); - - let inner = match self.0 { - IVecInner::Remote(ref base) => IVecInner::Subslice { - base: base.clone(), - offset: slice_offset, - len, - }, - IVecInner::Inline(_, old_inner) => { - // old length already checked above in assertion - let mut new_inner = Inner::default(); - new_inner[..len].copy_from_slice(&old_inner[slice_offset..slice_offset + len]); - - IVecInner::Inline(u8::try_from(len).expect(""), new_inner) - } - IVecInner::Subslice { - ref base, - ref offset, - .. - } => IVecInner::Subslice { - base: base.clone(), - offset: offset + slice_offset, - len, - }, - }; - - IVec(inner) - } - - fn inline(slice: &[u8]) -> Self { - assert!(is_inline_candidate(slice.len())); - - let mut data = Inner::default(); - - #[allow(unsafe_code)] - unsafe { - std::ptr::copy_nonoverlapping(slice.as_ptr(), data.as_mut_ptr(), slice.len()); - } - - Self(IVecInner::Inline( - u8::try_from(slice.len()).expect(""), - data, - )) - } - - fn remote(arc: Arc<[u8]>) -> Self { - Self(IVecInner::Remote(arc)) - } - - fn make_mut(&mut self) { - match self.0 { - IVecInner::Remote(ref mut buf) if Arc::strong_count(buf) != 1 => { - self.0 = IVecInner::Remote(buf.to_vec().into()); - } - IVecInner::Subslice { - ref mut base, - offset, - len, - } if Arc::strong_count(base) != 1 => { - self.0 = IVecInner::Remote(base[offset..offset + len].to_vec().into()); - } - _ => {} - } - } -} - -impl From<Box<[u8]>> for IVec { - fn from(b: Box<[u8]>) -> Self { - if is_inline_candidate(b.len()) { - Self::inline(&b) - } else { - Self::remote(Arc::from(b)) - } - } -} - -impl From<&[u8]> for IVec { - fn from(slice: &[u8]) -> Self { - if is_inline_candidate(slice.len()) { - Self::inline(slice) - } else { - Self::remote(Arc::from(slice)) - } - } -} - -impl From<Arc<[u8]>> for IVec { - fn from(arc: Arc<[u8]>) -> Self { - if is_inline_candidate(arc.len()) { - Self::inline(&arc) - } else { - Self::remote(arc) - } - } -} - -impl From<&IVec> for IVec { - fn from(v: &Self) -> Self { - v.clone() - } -} - -impl std::borrow::Borrow<[u8]> for IVec { - fn borrow(&self) -> &[u8] { - self.as_ref() - } -} - -impl std::borrow::Borrow<[u8]> for &IVec { - fn borrow(&self) -> &[u8] { - self.as_ref() - } -} - -macro_rules! from_array { - ($($s:expr),*) => { - $( - impl From<&[u8; $s]> for IVec { - fn from(v: &[u8; $s]) -> Self { - Self::from(&v[..]) - } - } - )* - } -} - -from_array!( - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32 -); - -impl Into<Arc<[u8]>> for IVec { - fn into(self) -> Arc<[u8]> { - match self.0 { - IVecInner::Inline(..) => Arc::from(self.as_ref()), - IVecInner::Remote(arc) => arc, - IVecInner::Subslice { .. } => self.deref().into(), - } - } -} - -impl Deref for IVec { - type Target = [u8]; - - #[inline] - fn deref(&self) -> &[u8] { - self.as_ref() - } -} - -impl AsRef<[u8]> for IVec { - #[inline] - #[allow(unsafe_code)] - fn as_ref(&self) -> &[u8] { - match &self.0 { - IVecInner::Inline(sz, buf) => unsafe { buf.get_unchecked(..*sz as usize) }, - IVecInner::Remote(buf) => buf, - IVecInner::Subslice { - ref base, - offset, - len, - } => &base[*offset..*offset + *len], - } - } -} - -impl DerefMut for IVec { - #[inline] - fn deref_mut(&mut self) -> &mut [u8] { - self.as_mut() - } -} - -impl AsMut<[u8]> for IVec { - #[inline] - #[allow(unsafe_code)] - fn as_mut(&mut self) -> &mut [u8] { - self.make_mut(); - - match &mut self.0 { - IVecInner::Inline(ref sz, ref mut buf) => unsafe { - std::slice::from_raw_parts_mut(buf.as_mut_ptr(), *sz as usize) - }, - IVecInner::Remote(ref mut buf) => Arc::get_mut(buf).expect(""), - IVecInner::Subslice { - ref mut base, - offset, - len, - } => &mut Arc::get_mut(base).expect("")[*offset..*offset + *len], - } - } -} - -impl Ord for IVec { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.as_ref().cmp(other.as_ref()) - } -} - -impl PartialOrd for IVec { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl<T: AsRef<[u8]>> PartialEq<T> for IVec { - fn eq(&self, other: &T) -> bool { - self.as_ref() == other.as_ref() - } -} - -impl PartialEq<[u8]> for IVec { - fn eq(&self, other: &[u8]) -> bool { - self.as_ref() == other - } -} - -impl Eq for IVec {} - -impl fmt::Debug for IVec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.as_ref().fmt(f) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn ivec_usage() { - let iv2 = IVec::from(&[4; 128][..]); - assert_eq!(iv2, vec![4; 128]); - } - - #[test] - fn boxed_slice_conversion() { - let boite1: Box<[u8]> = Box::new([1, 2, 3]); - let iv1: IVec = boite1.into(); - assert_eq!(iv1, vec![1, 2, 3]); - let boite2: Box<[u8]> = Box::new([4; 128]); - let iv2: IVec = boite2.into(); - assert_eq!(iv2, vec![4; 128]); - } - - #[test] - #[should_panic] - fn subslice_usage_00() { - let iv1 = IVec::from(&[1, 2, 3][..]); - let _subslice = iv1.subslice(0, 4); - } - - #[test] - #[should_panic] - fn subslice_usage_01() { - let iv1 = IVec::from(&[1, 2, 3][..]); - let _subslice = iv1.subslice(3, 1); - } - - #[test] - fn ivec_as_mut_identity() { - let initial = &[1]; - let mut iv = IVec::from(initial); - assert_eq!(&*initial, &*iv); - assert_eq!(&*initial, &mut *iv); - assert_eq!(&*initial, iv.as_mut()); - } -} diff --git a/rust-libs/tools/kv_typed/src/value.rs b/rust-libs/tools/kv_typed/src/value.rs deleted file mode 100644 index ec71f8da5..000000000 --- a/rust-libs/tools/kv_typed/src/value.rs +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (C) 2020 Éloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! KV Typed Value trait - -use crate::*; - -/// Trait to be implemented by the collection value -#[cfg(not(feature = "explorer"))] -pub trait Value: 'static + AsBytes + Debug + FromBytes + PartialEq + Send + Sync + Sized {} - -#[cfg(feature = "explorer")] -pub trait Value: - 'static + AsBytes + Debug + ExplorableValue + FromBytes + PartialEq + Send + Sync + Sized -{ -} - -#[cfg(not(feature = "explorer"))] -impl<T> Value for T where T: 'static + AsBytes + Debug + FromBytes + PartialEq + Send + Sync + Sized {} - -#[cfg(feature = "explorer")] -impl<T> Value for T where - T: 'static + AsBytes + Debug + ExplorableValue + FromBytes + PartialEq + Send + Sync + Sized -{ -} - -pub trait ValueZc: Value { - type Ref: Sized + zerocopy::AsBytes + zerocopy::FromBytes; -} - -impl ValueZc for () { - type Ref = (); -} - -macro_rules! impl_value_zc_for_numbers { - ($($T:ty),*) => {$( - impl ValueZc for $T { - type Ref = Self; - } - )*}; -} -impl_value_zc_for_numbers!( - usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64 -); - -pub trait ValueSliceZc: Value { - type Elem: Sized + zerocopy::AsBytes + zerocopy::FromBytes; - - fn prefix_len() -> usize { - 8 - } -} - -impl ValueSliceZc for () { - type Elem = (); - - fn prefix_len() -> usize { - 0 - } -} - -impl ValueSliceZc for String { - type Elem = u8; - - fn prefix_len() -> usize { - 0 - } -} - -impl<T, E> ValueSliceZc for Vec<T> -where - T: 'static - + Copy - + Debug - + Default - + Display - + FromStr<Err = E> - + PartialEq - + Send - + Sized - + Sync - + zerocopy::AsBytes - + zerocopy::FromBytes, - E: Error + Send + Sync + 'static, -{ - type Elem = T; - - fn prefix_len() -> usize { - 0 - } -} - -macro_rules! impl_value_slice_zc_for_smallvec { - ($($N:literal),*) => {$( - impl<T, E> ValueSliceZc for SmallVec<[T; $N]> - where - T: 'static - + Copy - + Debug - + Default - + Display - + FromStr<Err = E> - + PartialEq - + Send - + Sized - + Sync - + zerocopy::AsBytes - + zerocopy::FromBytes, - E: Error + Send + Sync + 'static, - { - type Elem = T; - - fn prefix_len() -> usize { - 0 - } - } - )*}; -} -impl_value_slice_zc_for_smallvec!(2, 4, 8, 16, 32, 64); - -impl<T, E> ValueSliceZc for BTreeSet<T> -where - T: 'static - + Copy - + Debug - + Default - + Display - + FromStr<Err = E> - + Ord - + PartialEq - + Send - + Sized - + Sync - + zerocopy::AsBytes - + zerocopy::FromBytes, - E: Error + Send + Sync + 'static, -{ - type Elem = T; - - fn prefix_len() -> usize { - 0 - } -} diff --git a/rust-libs/tools/kv_typed/tests/test_db_schema.rs b/rust-libs/tools/kv_typed/tests/test_db_schema.rs deleted file mode 100644 index 7f2432b61..000000000 --- a/rust-libs/tools/kv_typed/tests/test_db_schema.rs +++ /dev/null @@ -1,221 +0,0 @@ -use kv_typed::backend::memory::Mem; -use kv_typed::db_schema; -use kv_typed::prelude::*; -use std::collections::BTreeSet; - -db_schema!( - TestV1, - [ - ["c1", Col1, i32, String], - ["c2", Col2, usize, ()], - ["c3", Col3, U32BE, Vec<u128>], - ["c4", Col4, U64BE, BTreeSet<u128>], - ] -); - -#[test] -#[allow(clippy::eq_op)] -fn test_macro_db() { - assert_eq!(Col1Event::RemoveAll, Col1Event::RemoveAll); - - #[cfg(feature = "explorer")] - { - use kv_typed::explorer::DbExplorable as _; - assert_eq!( - TestV1Db::<Mem>::list_collections(), - vec![ - ("col1", "i32", "String"), - ("col2", "usize", "()"), - ("col3", "U32BE", "Vec<u128>"), - ("col4", "U64BE", "BTreeSet<u128>") - ] - ); - } -} - -#[test] -fn test_db_mem() -> KvResult<()> { - let db = TestV1Db::<kv_typed::backend::memory::Mem>::open( - kv_typed::backend::memory::MemConf::default(), - )?; - - test_db(&db) -} - -//#[cfg(feature = "sled_backend")] -#[test] -fn test_db_sled() -> KvResult<()> { - let db = TestV1Db::<Sled>::open(SledConf::default().temporary(true))?; - - test_db(&db) -} - -fn test_db<B: Backend>(db: &TestV1Db<B>) -> KvResult<()> { - let (sender, recv) = kv_typed::channel::unbounded(); - db.col1().subscribe(sender)?; - - let db2 = db.clone(); - - let handler = std::thread::spawn(move || db2.col1_write().upsert(3, "toto".to_owned())); - handler.join().expect("thread panic")?; - - let expected_events: Events<Col1Event> = smallvec::smallvec![Col1Event::Upsert { - key: 3, - value: "toto".to_owned(), - }]; - if let Ok(msg) = recv.recv() { - assert_eq!(msg.as_ref(), &expected_events,) - } else { - panic!("must be receive event") - } - - assert_eq!(db.col1().get(&3)?, Some("toto".to_owned()),); - let d = db.col1().get_ref_slice(&3, |bytes| { - let str_ = unsafe { core::str::from_utf8_unchecked(bytes) }; - assert_eq!("toto", str_); - assert_eq!(db.col2().get(&3)?, None,); - Ok(str_.to_owned()) - })?; - assert_eq!(d, Some("toto".to_owned())); - - assert_eq!(db.col2().get(&3)?, None,); - db.col2_write().upsert(3, ())?; - assert_eq!(db.col2().get(&3)?, Some(()),); - - db.col1_write().upsert(5, "tutu".to_owned())?; - - db.col1().iter(.., |mut iter| { - assert_eq!(iter.next_res()?, Some((3, "toto".to_owned()))); - assert_eq!(iter.next_res()?, Some((5, "tutu".to_owned()))); - assert_eq!(iter.next_res()?, None); - Ok::<(), KvError>(()) - })?; - - db.col1().iter_rev(.., |it| { - let mut iter = it.values(); - - assert_eq!(iter.next_res()?, Some("tutu".to_owned())); - assert_eq!(iter.next_res()?, Some("toto".to_owned())); - assert_eq!(iter.next_res()?, None); - Ok::<(), KvError>(()) - })?; - - db.col1_write().upsert(7, "titi".to_owned())?; - - db.col1().iter_rev(.., |it| { - let mut iter = it.values().step_by(2); - - assert_eq!(iter.next_res()?, Some("titi".to_owned())); - assert_eq!(iter.next_res()?, Some("toto".to_owned())); - assert_eq!(iter.next_res()?, None); - - Ok::<(), KvError>(()) - })?; - - db.col3_write().upsert(U32BE(4), vec![1, 2, 3])?; - db.col3().get_ref_slice(&U32BE(4), |numbers| { - assert_eq!(numbers, &[1, 2, 3]); - Ok(()) - })?; - - // Test get_ref_slice - db.col4_write() - .upsert(U64BE(4), (&[3, 2, 4, 1]).iter().copied().collect())?; - db.col4().get_ref_slice(&U64BE(4), |numbers| { - assert_eq!(numbers, &[1, 2, 3, 4]); - Ok(()) - })?; - - // Test iter_ref_slice - let vec: Vec<(U32BE, Vec<u128>)> = db - .col3() - .iter_ref_slice(.., |k, v_slice| Ok((k.into(), Vec::from(v_slice)))) - .collect::<KvResult<_>>()?; - assert_eq!(vec, vec![(U32BE(4), vec![1, 2, 3])]); - - // Test transactional - // A read tx should be opened when write tx not commited - let (s1, r1) = flume::bounded::<()>(0); - let (s2, r2) = flume::bounded::<()>(0); - let db_ro = db.get_ro_handler(); - let read_task = std::thread::spawn(move || { - r1.recv().expect("disconnected"); - (db_ro.col3(), db_ro.col4(), db_ro.col2()).read(|(c3, c4, _c2)| { - c3.get_ref_slice(&U32BE(4), |numbers| { - assert_eq!(numbers, &[1, 2, 3]); - Ok(()) - })?; - c3.iter(.., |it| { - let iter = it.keys(); - s2.send(()).expect("disconnected"); - assert_eq!(iter.collect::<KvResult<Vec<_>>>()?, vec![U32BE(4)]); - Ok::<(), KvError>(()) - })?; - c4.get_ref_slice(&U64BE(4), |numbers| { - assert_eq!(numbers, &[1, 2, 3, 4]); - Ok(()) - })?; - Ok(()) - }) - }); - - let tres: KvResult<()> = - (db.col3_write(), db.col4_write(), db.col2_write()).write(|(mut c3, mut c4, _c2)| { - s1.send(()).expect("disconnected"); - assert_eq!( - c3.iter(.., |it| it.keys().collect::<KvResult<Vec<_>>>())?, - vec![U32BE(4)] - ); - assert_eq!( - c3.iter(.., |it| it.values().collect::<KvResult<Vec<_>>>())?, - vec![vec![1, 2, 3]] - ); - c3.upsert(U32BE(42), vec![5, 4, 6]); - assert_eq!( - c3.iter(.., |it| it.keys().collect::<KvResult<Vec<_>>>())?, - vec![U32BE(4), U32BE(42)] - ); - assert_eq!( - c3.iter_rev(.., |it| it.keys().collect::<KvResult<Vec<_>>>())?, - vec![U32BE(42), U32BE(4)] - ); - c3.upsert(U32BE(8), vec![11, 12, 13]); - c3.remove(U32BE(4)); - assert_eq!( - c3.iter(.., |it| it.keys().collect::<KvResult<Vec<_>>>())?, - vec![U32BE(8), U32BE(42)] - ); - c3.iter_rev(.., |it| { - let iter = it.keys(); - r2.recv().expect("disconnected"); - assert_eq!( - iter.collect::<KvResult<Vec<_>>>()?, - vec![U32BE(42), U32BE(8)] - ); - - Ok::<(), KvError>(()) - })?; - c4.upsert(U64BE(4), (&[7, 8, 6, 5]).iter().copied().collect()); - Ok(()) - }); - tres?; - read_task.join().expect("read task panic")?; - - // Test clear() - db.col4_write().clear()?; - assert_eq!(db.col4().count()?, 0); - - // Test transactional 2 - db.write(|mut db_tx| { - db_tx - .col4 - .upsert(U64BE(47), (&[5, 9, 3, 2]).iter().copied().collect()); - Ok(()) - })?; - db.col4().get_ref_slice(&U64BE(47), |numbers| { - assert_eq!(numbers, &[2, 3, 5, 9]); - Ok(()) - })?; - - Ok(()) -} diff --git a/rust-libs/tools/kv_typed/tests/test_mock.rs b/rust-libs/tools/kv_typed/tests/test_mock.rs deleted file mode 100644 index 8f68164a2..000000000 --- a/rust-libs/tools/kv_typed/tests/test_mock.rs +++ /dev/null @@ -1,54 +0,0 @@ -#[cfg(feature = "mock")] -mod tests { - - use kv_typed::prelude::*; - use mockall::predicate::*; - use std::fmt::Debug; - use std::ops::{Bound, RangeFull}; - - db_schema!( - Test, - [["c1", col_1, u32, String], ["c2", col_2, String, u64],] - ); - - fn use_readable_db<DB: TestDbReadable>(db: &DB) -> KvResult<()> { - let col1_reader = db.col_1(); - assert_eq!(col1_reader.count()?, 899); - assert_eq!(col1_reader.get(&42)?, Some("toto".to_owned())); - let mut iter = col1_reader.iter(..); - assert_eq!(iter.next_res()?, Some((42, "toto".to_owned()))); - assert_eq!(iter.next_res()?, None); - Ok(()) - } - - #[test] - fn test_mock_db() -> KvResult<()> { - let mut db = MockTestDbReadable::new(); - db.expect_col_1().times(1).returning(|| { - let mut col_1 = MockColRo::<Col1Event>::new(); - col_1.expect_count().times(1).returning(|| Ok(899)); - col_1 - .expect_get() - .times(1) - .returning(|_| Ok(Some("toto".to_owned()))); - col_1.expect_iter::<RangeFull>().times(1).returning(|_| { - let mut b_iter = MockBackendIter::new(); - #[allow(clippy::string_lit_as_bytes)] - let mut items = vec![ - None, - Some(Ok((vec![0u8, 0, 0, 42], "toto".as_bytes().to_vec()))), - ]; - b_iter - .expect_next() - .times(2) - .returning(move || items.pop().unwrap_or(None)); - KvIter::new(b_iter, (Bound::Unbounded, Bound::Unbounded)) - }); - col_1 - }); - - use_readable_db(&db)?; - - Ok(()) - } -} -- GitLab