// 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 .
#![deny(
clippy::unwrap_used,
missing_copy_implementations,
trivial_casts,
trivial_numeric_casts,
unstable_features,
unused_import_braces
)]
mod anti_spam;
mod warp_;
use async_graphql::http::GraphQLPlaygroundConfig;
use duniter_core::common::{currency_params::CurrencyParameters, prelude::*};
use duniter_core::dbs::databases::txs_mp_v2::TxsMpV2DbReadable;
use duniter_core::dbs::prelude::*;
use duniter_core::dbs::{kv_typed::prelude::*, FileBackend};
use duniter_core::documents::transaction::TransactionDocumentV10;
use duniter_core::global::AsyncAccessor;
use duniter_core::mempools::Mempools;
#[cfg(not(test))]
use duniter_core::module::public_ips::get_public_ips;
use duniter_core::{block::DubpBlockV10, crypto::hashs::Hash};
use duniter_core::{
common::crypto::keys::{ed25519::PublicKey, KeyPair as _},
crypto::keys::ed25519::Ed25519KeyPair,
};
use duniter_core::{conf::DuniterMode, module::Endpoint};
use duniter_gva_conf::GvaConf;
use duniter_gva_db::*;
use duniter_gva_gql::{GvaSchema, QueryContext};
use duniter_gva_indexer::{get_gva_db_ro, get_gva_db_rw};
use futures::{StreamExt, TryStreamExt};
use std::{convert::Infallible, path::Path};
#[cfg(test)]
use tests::get_public_ips;
use warp::{http::Response as HttpResponse, Filter as _, Rejection};
const PLAYGROUND_SUB_PATH: &str = "playground";
const SUBSCRIPTION_SUB_PATH: &str = "subscription";
#[derive(Debug)]
pub struct GvaModule {
conf: GvaConf,
currency: String,
dbs_pool: fast_threadpool::ThreadPoolAsyncHandler>,
gva_db_ro: &'static GvaV1DbRo,
mempools: Mempools,
mode: DuniterMode,
self_keypair: Ed25519KeyPair,
software_version: &'static str,
}
#[async_trait::async_trait]
impl duniter_core::module::DuniterModule for GvaModule {
const INDEX_BLOCKS: bool = true;
const MODULE_NAME: &'static str = "gva";
type Conf = GvaConf;
fn apply_block(
block: &DubpBlockV10,
_conf: &duniter_core::conf::DuniterCoreConf,
currency_params: CurrencyParameters,
profile_path_opt: Option<&Path>,
) -> KvResult<()> {
if let Some(profile_path) = profile_path_opt {
let gva_db = get_gva_db_rw(profile_path_opt);
duniter_gva_indexer::apply_block_blocks_chunk(&block, &gva_db, profile_path)?;
duniter_gva_indexer::apply_block(&block, currency_params, gva_db)
} else {
let gva_db = get_gva_db_rw(profile_path_opt);
duniter_gva_indexer::apply_block(&block, currency_params, gva_db)
}
}
fn revert_block(
block: &DubpBlockV10,
_conf: &duniter_core::conf::DuniterCoreConf,
currency_params: CurrencyParameters,
profile_path_opt: Option<&Path>,
) -> KvResult<()> {
if let Some(profile_path) = profile_path_opt {
let gva_db = get_gva_db_rw(profile_path_opt);
duniter_gva_indexer::revert_block_blocks_chunk(&block, &gva_db, profile_path)?;
duniter_gva_indexer::revert_block(&block, currency_params, gva_db)
} else {
let gva_db = get_gva_db_rw(profile_path_opt);
duniter_gva_indexer::revert_block(&block, currency_params, gva_db)
}
}
async fn init(
conf: Self::Conf,
core_conf: &duniter_core::conf::DuniterCoreConf,
currency: &str,
dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler>,
mempools: Mempools,
mode: duniter_core::conf::DuniterMode,
profile_path_opt: Option<&Path>,
software_version: &'static str,
) -> anyhow::Result<(Self, Vec)> {
let self_keypair = core_conf.self_key_pair.clone();
let endpoints = Self::gen_endpoints(&conf).await?;
Ok((
GvaModule {
conf,
currency: currency.to_owned(),
dbs_pool: dbs_pool.to_owned(),
gva_db_ro: get_gva_db_ro(profile_path_opt),
mempools,
mode,
self_keypair,
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 conf.enabled {
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>,
profile_path_opt: Option<&Path>,
pubkey: PublicKey,
) -> KvResult