// 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_;
pub use duniter_core::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_core::conf::DuniterMode;
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::global::AsyncAccessor;
use duniter_core::mempools::Mempools;
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};
use warp::{http::Response as HttpResponse, Filter as _, Rejection};
#[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;
fn apply_block(
block: &DubpBlockV10,
_conf: &duniter_core::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_core::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_core::conf::DuniterConf,
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 = conf.self_key_pair.clone();
let conf = conf.gva.clone();
let remote_port = conf.get_remote_port();
let mut endpoints = Vec::new();
if conf.enabled() {
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,
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