diff --git a/Cargo.lock b/Cargo.lock index 7f63f1eaf27cec61beeed2e581db25d5ec8ec364..43b8d55edcf7f7f8fe9c3d2853c1fa33c31c4b5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1132,6 +1132,7 @@ dependencies = [ "http", "log", "resiter", + "serde", "serde_urlencoded 0.7.0", "smallvec", "tokio", diff --git a/app/lib/common-libs/programOptions.ts b/app/lib/common-libs/programOptions.ts index 505cd5caf3bf14d1015f5c4a8cb100e95e70cf83..6ec4f1bb06caf846d0eb1f9995dd6e41042fb172 100644 --- a/app/lib/common-libs/programOptions.ts +++ b/app/lib/common-libs/programOptions.ts @@ -29,7 +29,7 @@ export interface ProgramOptions { sqlTraces?: boolean; memory?: boolean; gva?: boolean; - nogva?: boolean; + noGva?: boolean; } export const cliprogram: ProgramOptions = { diff --git a/app/lib/dal/fileDAL.ts b/app/lib/dal/fileDAL.ts index a42a582fddeab8430bd776d8d707edf8f19c9196..0353b71176cc52226190ec4101cf0aa0c7d7468f 100644 --- a/app/lib/dal/fileDAL.ts +++ b/app/lib/dal/fileDAL.ts @@ -79,6 +79,7 @@ import { LevelDBIindex } from "./indexDAL/leveldb/LevelDBIindex"; import { LevelDBMindex } from "./indexDAL/leveldb/LevelDBMindex"; import { ConfDAO } from "./indexDAL/abstract/ConfDAO"; import { ServerDAO } from "./server-dao"; +import { PeerDTO } from "../dto/PeerDTO"; const readline = require("readline"); const indexer = require("../indexer").Indexer; @@ -233,12 +234,12 @@ export class FileDAL implements ServerDAO { } initRustServer(conf: ConfDTO, commandName: string | null = null) { - let serverPubkey = conf.pair ? conf.pair.pub : null; + let selfPubkey = conf.pair ? conf.pair.pub : null; let rustServerConf = { command: commandName, currency: conf.currency || "", gva: conf.gva, - serverPubkey, + selfPubkey, txsMempoolSize: conf.txsMempoolSize || constants.SANDBOX_SIZE_TRANSACTIONS, }; @@ -1674,7 +1675,6 @@ export class FileDAL implements ServerDAO { unitbase, local_iindex ); - // TODO ESZ: call rust server: write_ud_sources(udSources: SimpleUdEntryForWallet[]) return udSources; } return []; diff --git a/app/lib/dto/ConfDTO.ts b/app/lib/dto/ConfDTO.ts index 7ddc0bbc3d6484d77d55a571a919f6e8367d49dd..b80564a06834daa699c15a152aab5d86b04b3066 100644 --- a/app/lib/dto/ConfDTO.ts +++ b/app/lib/dto/ConfDTO.ts @@ -183,9 +183,13 @@ export class ConfDTO public gva?: { host?: string; port?: number; - remotehost?: string | null; - remoteport?: number | null; - remotepath?: string; + path?: string; + subscriptionsPath?: string; + remoteHost?: string; + remotePort?: number; + remotePath?: string; + remoteSubscriptionsPath?: string; + remoteTls?: boolean; }, public ws2p?: { privateAccess?: boolean; diff --git a/app/modules/config.ts b/app/modules/config.ts index 9ff3ced8561b0605258f329b4ce6532cdebe5008..2dfe10269ade0665d43e9f1ae8f39781df5af346 100644 --- a/app/modules/config.ts +++ b/app/modules/config.ts @@ -26,6 +26,10 @@ module.exports = { value: "--gva", desc: "Enable gva API and database.", }, + { + value: "--no-gva", + desc: "Disable gva API and database.", + }, ], config: { @@ -39,13 +43,24 @@ module.exports = { if ( program.gva && program.gva === true && - (!program.nogva || program.nogva === undefined) + (!program.noGva || program.noGva === undefined) ) { - conf.gva = { - host: "localhost", - port: 30901, - }; - } else if (program.nogva) { + // Fill with default conf if needed + if (conf.gva) { + conf.gva.host = conf.gva.host || "localhost"; + conf.gva.port = conf.gva.port || 30901; + conf.gva.path = conf.gva.path || "gva"; + conf.gva.subscriptionsPath = + conf.gva.subscriptionsPath || "gva-sub"; + } else { + conf.gva = { + host: "localhost", + port: 30901, + path: "gva", + subscriptionsPath: "gva-sub", + }; + } + } else if (program.noGva) { conf.gva = undefined; } }, diff --git a/app/modules/peersignal.ts b/app/modules/peersignal.ts index d4f650a7d1dbec7d06d017b74978c6799b633936..a37d6531356def7b65d8e5fb1acbb19936b3cdba 100644 --- a/app/modules/peersignal.ts +++ b/app/modules/peersignal.ts @@ -14,6 +14,7 @@ "use strict"; import { ConfDTO } from "../lib/dto/ConfDTO"; import { Server } from "../../server"; +import { PeerDTO } from "../lib/dto/PeerDTO"; const async = require("async"); const constants = require("../lib/constants"); @@ -56,10 +57,15 @@ class PeerSignalEmitter { this.INTERVAL = setInterval(() => { this.peerFifo.push(async (done: any) => { try { - await this.server.PeeringService.generateSelfPeer( + let selfPeer = await this.server.PeeringService.generateSelfPeer( this.conf, SIGNAL_INTERVAL ); + if (selfPeer) { + this.server.dal.rustServer.updateSelfPeer( + PeerDTO.fromDBPeer(selfPeer) + ); + } done(); } catch (e) { done(e); @@ -68,14 +74,15 @@ class PeerSignalEmitter { }, SIGNAL_INTERVAL); // Launches it a first time few seconds after startup - setTimeout( - () => - this.server.PeeringService.generateSelfPeer( - this.conf, - SIGNAL_INTERVAL - SIGNAL_INITIAL_DELAY - ), - 0 - ); + setTimeout(async () => { + let selfPeer = await this.server.PeeringService.generateSelfPeer( + this.conf, + SIGNAL_INTERVAL - SIGNAL_INITIAL_DELAY + ); + if (selfPeer) { + this.server.dal.rustServer.updateSelfPeer(PeerDTO.fromDBPeer(selfPeer)); + } + }, 0); } stopService() { diff --git a/doc/use/configure.md b/doc/use/configure.md index 229eacba4b02984bf220fdbedf67867d82ab1541..4d3d1a371a5975ee59a7fff7fd0a7e9248998251 100644 --- a/doc/use/configure.md +++ b/doc/use/configure.md @@ -185,15 +185,21 @@ This mode is optional if only because technically it is sometimes difficult or e GVA is still disabled by default. To enable it you have to add the option `--gva` during synchronization and at each start of your duniter node (`duniter start --gva`). -GVA is not yet configurable from the command line, but it is possible to use environment variables : +GVA is not yet configurable from the command line, but it is possible to manually edit `conf.json` file : -| parameter | env var | default value | +| parameter | type | default value | |:-:|:-:|:-:| -| remote_path | `DUNITER_GVA_REMOTE_PATH` | `/gva` +| host | string | `"localhost"` | +| port | number | `30901` | +| path | string | `"gva"` | +| remotePath | string | `"gva"` | +| subscriptionsPath | string | `"gva-sub"` | +| remoteSubscriptionsPath | string | `"gva-sub"` | +| remoteTls | boolean | `false` | -GVA server listen to `localhost:10901/remote_path` +GVA server listen to `http://<host>:<port>/<remotePath>` -GVA subscriptions websocket server listen to `localhost:10901/gva-sub` +GVA subscriptions websocket server listen to `ws://<host>:<port>/<remoteSubscriptionsPath>` ## Synchronize your node diff --git a/neon/native/server.d.ts b/neon/native/server.d.ts index ca66fa33461c33e68581e7012cdf18c39829db51..0e194c0951b9632e7294788fa44e1485e3f66ec3 100644 --- a/neon/native/server.d.ts +++ b/neon/native/server.d.ts @@ -6,13 +6,25 @@ export class RustServerConf { command: string | null currency: string gva: GvaConf | undefined - serverPubkey: string | null + selfPubkey: string | null txsMempoolSize: number } export class GvaConf { host?: string port?: number + path?: string; + subscriptionsPath?: string; +} + +export class PeerCard { + version: number + currency: string + pubkey: string + blockstamp: string + endpoints: string[] + signature: string + status: string } export class RustDbTx { @@ -87,4 +99,5 @@ export class RustServer { applyBlock(block: BlockDTOV10): void; applyChunkOfBlocks(blocks: BlockDTOV10[]): void; trimExpiredNonWrittenTxs(limitTime: number): void; + updateSelfPeer(peer: PeerCard): void; } diff --git a/neon/native/src/server.rs b/neon/native/src/server.rs index f89f2344c397389c549c87fb37e1ec3bce0db110..5bf99530dd818821501e6ef85c98765f80c8671d 100644 --- a/neon/native/src/server.rs +++ b/neon/native/src/server.rs @@ -21,7 +21,7 @@ use dubp::documents::{ transaction::{TransactionDocumentV10, TransactionDocumentV10Stringified}, }; use dubp::documents_parser::prelude::*; -use duniter_server::{DuniterServer, DuniterServerConf, GvaConf}; +use duniter_server::{DuniterServer, DuniterServerConf, GvaConf, PeerCardStringified}; use neon::declare_types; use neon::prelude::*; use serde::{Deserialize, Serialize}; @@ -47,19 +47,29 @@ declare_types! { if let Some(port) = gva_conf_stringified.port { gva_conf.port(port); } + if let Some(path) = gva_conf_stringified.path { + gva_conf.path(path); + } + if let Some(subscriptions_path) = gva_conf_stringified.subscriptions_path { + gva_conf.subscriptions_path(subscriptions_path); + } Some(gva_conf) } else { None }; let command_name = rust_server_conf_stringified.command_name; let currency = rust_server_conf_stringified.currency; - let server_pubkey = if let Some(server_pubkey_str) = rust_server_conf_stringified.server_pubkey { - into_neon_res(&mut cx, PublicKey::from_base58(&server_pubkey_str))? + let server_pubkey = if let Some(self_pubkey_str) = rust_server_conf_stringified.self_pubkey { + into_neon_res(&mut cx, PublicKey::from_base58(&self_pubkey_str))? } else { PublicKey::default() }; let txs_mempool_size = rust_server_conf_stringified.txs_mempool_size as usize; - let conf = DuniterServerConf { gva: gva_conf, server_pubkey, txs_mempool_size }; + let conf = DuniterServerConf { + gva: gva_conf, + self_pubkey: server_pubkey, + txs_mempool_size + }; let home_path_opt = if let Some(arg1) = arg1_opt { if arg1.is_a::<JsString>() { @@ -289,6 +299,19 @@ declare_types! { }.map(|()| cx.undefined().upcast()); into_neon_res(&mut cx, res) } + method updateSelfPeer(mut cx) { + let peer_js = cx.argument::<JsValue>(0)?; + + let peer_stringified: PeerCardStringified = neon_serde::from_value(&mut cx, peer_js)?; + + let this = cx.this(); + { + let guard = cx.lock(); + let server = this.borrow(&guard); + server.server.update_self_peer(peer_stringified) + }; + Ok(cx.undefined().upcast()) + } } } @@ -298,7 +321,7 @@ struct RustServerConfStringified { command_name: Option<String>, currency: String, gva: Option<GvaConfStringified>, - server_pubkey: Option<String>, + self_pubkey: Option<String>, txs_mempool_size: u32, } @@ -307,6 +330,8 @@ struct RustServerConfStringified { struct GvaConfStringified { host: Option<String>, port: Option<u16>, + path: Option<String>, + subscriptions_path: Option<String>, } #[derive(Deserialize, Serialize)] diff --git a/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs b/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs index dbdad922ffe65a1b7fa574d1cb1fbf8a6214569f..cf714942acd5200eaaf7b6dd9cdc926017c35fda 100644 --- a/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs +++ b/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs @@ -54,7 +54,6 @@ pub(crate) fn write_gva_tx<B: Backend>( // Remove consumed UTXOs for input in tx.get_inputs() { - // TODO ESZ remove UD sources if let SourceIdV10::Utxo(utxo_id) = input.id { let db_tx_origin = gva_db .txs() @@ -147,7 +146,6 @@ pub(crate) fn revert_tx<B: Backend>( } // Recreate UTXOs consumed by this tx for input in tx_db.tx.get_inputs() { - // TODO ESZ recreate UD sources if let SourceIdV10::Utxo(utxo_id) = input.id { let db_tx_origin = gva_db .txs() diff --git a/rust-libs/duniter-gva/Cargo.toml b/rust-libs/duniter-gva/Cargo.toml index c7dc21259e018a9f98057032161a0ac7ea5c1d18..93c56d4099841561d10626e564ef3e3ce353634d 100644 --- a/rust-libs/duniter-gva/Cargo.toml +++ b/rust-libs/duniter-gva/Cargo.toml @@ -18,6 +18,7 @@ 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" smallvec = { version = "1.4.0", features = ["serde", "write"] } tokio = { version = "0.2.22", features = ["io-util", "rt-threaded", "stream"] } diff --git a/rust-libs/duniter-gva/src/entities.rs b/rust-libs/duniter-gva/src/entities.rs index d4ceff8b25981f29935fc58d7c09dbd2f8e04c03..77860bf00dd565a5998f9ca10ce9a64d44aa6351 100644 --- a/rust-libs/duniter-gva/src/entities.rs +++ b/rust-libs/duniter-gva/src/entities.rs @@ -18,6 +18,18 @@ pub mod ud_gva; use crate::*; +#[derive(async_graphql::SimpleObject)] +pub(crate) struct TxsHistoryGva { + /// Transactions sent + pub(crate) sent: Vec<TxGva>, + /// Transactions sending + pub(crate) sending: Vec<TxGva>, + /// Transactions received + pub(crate) received: Vec<TxGva>, + /// Transactions receiving + pub(crate) receiving: Vec<TxGva>, +} + #[derive(Clone, async_graphql::SimpleObject)] pub(crate) struct UtxoGva { /// Source amount @@ -31,15 +43,3 @@ pub(crate) struct UtxoGva { /// Written time pub(crate) written_time: i64, } - -#[derive(async_graphql::SimpleObject)] -pub(crate) struct TxsHistoryGva { - /// Transactions sent - pub(crate) sent: Vec<TxGva>, - /// Transactions sending - pub(crate) sending: Vec<TxGva>, - /// Transactions received - pub(crate) received: Vec<TxGva>, - /// Transactions receiving - pub(crate) receiving: Vec<TxGva>, -} diff --git a/rust-libs/duniter-gva/src/lib.rs b/rust-libs/duniter-gva/src/lib.rs index 4c058c92af014c1bb06e9b57a4c56f1bd546a904..7d542244d4f120cec2bab0ad5e72075e4d40b09e 100644 --- a/rust-libs/duniter-gva/src/lib.rs +++ b/rust-libs/duniter-gva/src/lib.rs @@ -59,7 +59,7 @@ use warp::{http::Response as HttpResponse, Filter as _, Rejection, Stream}; pub struct GvaConf { host: String, port: u16, - remote_path: String, + path: String, subscriptions_path: String, } @@ -68,7 +68,7 @@ impl Default for GvaConf { GvaConf { host: "localhost".to_owned(), port: 30901, - remote_path: "gva".to_owned(), + path: "gva".to_owned(), subscriptions_path: "gva-sub".to_owned(), } } @@ -81,12 +81,20 @@ impl GvaConf { pub fn port(&mut self, port: u16) { self.port = port; } - pub fn remote_path(&mut self, mut remote_path: String) { - if remote_path.starts_with('/') { - remote_path.remove(0); - self.remote_path = remote_path; + pub fn path(&mut self, mut path: String) { + if path.starts_with('/') { + path.remove(0); + self.path = path; } else { - self.remote_path = remote_path; + self.path = path; + } + } + pub fn subscriptions_path(&mut self, mut subscriptions_path: String) { + if subscriptions_path.starts_with('/') { + subscriptions_path.remove(0); + self.subscriptions_path = subscriptions_path; + } else { + self.subscriptions_path = subscriptions_path; } } } @@ -94,14 +102,19 @@ impl GvaConf { #[derive(Clone, Copy, Debug)] pub struct GvaServer; +#[derive(Debug, Default)] +pub struct ServerMetaData { + pub currency: String, + pub self_pubkey: PublicKey, + pub software_version: &'static str, +} + impl GvaServer { pub fn start( conf: GvaConf, - currency: String, dbs: DuniterDbs, dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, - server_pubkey: PublicKey, - software_version: &'static str, + server_meta_data: ServerMetaData, txs_mempool: TxsMempool, ) -> Result<(), tokio::io::Error> { println!("TMP GvaServer::start: conf={:?}", conf); @@ -117,11 +130,9 @@ impl GvaServer { subscriptions::SubscriptionRoot::default(), ) .data(schema::SchemaData { - currency, dbs, dbs_pool, - server_pubkey, - software_version, + server_meta_data, txs_mempool, }) .extension(async_graphql::extensions::Logger) @@ -134,22 +145,20 @@ impl GvaServer { ); let conf_clone = conf.clone(); - let graphql_playground = warp::path::path(conf.remote_path.clone()) - .and(warp::get()) - .map(move || { - HttpResponse::builder() - .header("content-type", "text/html") - .body(async_graphql::http::playground_source( - GraphQLPlaygroundConfig::new(&format!( - "/{}", - &conf_clone.remote_path + let graphql_playground = + warp::path::path(conf.path.clone()) + .and(warp::get()) + .map(move || { + HttpResponse::builder() + .header("content-type", "text/html") + .body(async_graphql::http::playground_source( + GraphQLPlaygroundConfig::new(&format!("/{}", &conf_clone.path)) + .subscription_endpoint(&format!( + "/{}", + &conf_clone.subscriptions_path, + )), )) - .subscription_endpoint(&format!( - "/{}", - &conf_clone.subscriptions_path, - )), - )) - }); + }); let routes = graphql_playground .or(graphql_post) @@ -171,7 +180,7 @@ impl GvaServer { log::info!( "Start GVA server at http://localhost:{}/{}", conf.port, - &conf.remote_path + &conf.path ); warp::serve(routes).run(([0, 0, 0, 0], conf.port)).await; }); @@ -181,10 +190,39 @@ impl GvaServer { } } +#[derive( + async_graphql::SimpleObject, Clone, Debug, Default, serde::Deserialize, serde::Serialize, +)] +#[serde(rename_all = "camelCase")] +#[graphql(name = "PeerCard")] +pub struct PeerCardStringified { + 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 PeerCardStringified { + 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, + } + } +} + #[cfg(test)] mod tests { use super::*; use duniter_dbs::bc_v2::{BcV2Db, BcV2DbWritable}; + use duniter_dbs::cm_v1::{CmV1Db, CmV1DbWritable}; use duniter_dbs::kv_typed::backend::memory::{Mem, MemConf}; use duniter_dbs::{GvaV1Db, GvaV1DbWritable, TxsMpV2Db, TxsMpV2DbWritable}; use fast_threadpool::ThreadPoolConfig; @@ -195,6 +233,7 @@ mod tests { fn launch_mem_gva() { let dbs = DuniterDbs { bc_db: unwrap!(BcV2Db::<Mem>::open(MemConf::default())), + cm_db: unwrap!(CmV1Db::<MemSingleton>::open(MemSingletonConf::default())), gva_db: unwrap!(GvaV1Db::<Mem>::open(MemConf::default())), txs_mp_db: unwrap!(TxsMpV2Db::<Mem>::open(MemConf::default())), }; @@ -203,11 +242,9 @@ mod tests { unwrap!(GvaServer::start( GvaConf::default(), - "test".to_owned(), dbs, threadpool.into_async_handler(), - PublicKey::default(), - "test", + ServerMetaData::default(), TxsMempool::new(10) )); diff --git a/rust-libs/duniter-gva/src/mutations.rs b/rust-libs/duniter-gva/src/mutations.rs index 770f5be3aaa57f211b7795a9d7df78bb71c90323..dff0edd7411766235053dbfa743aa5a19285a0de 100644 --- a/rust-libs/duniter-gva/src/mutations.rs +++ b/rust-libs/duniter-gva/src/mutations.rs @@ -33,7 +33,7 @@ impl MutationRoot { let data = ctx.data::<SchemaData>()?; - let server_pubkey = data.server_pubkey; + let server_pubkey = data.server_meta_data.self_pubkey; let txs_mempool = data.txs_mempool; let tx = data @@ -62,7 +62,7 @@ impl MutationRoot { let data = ctx.data::<SchemaData>()?; - let server_pubkey = data.server_pubkey; + let server_pubkey = data.server_meta_data.self_pubkey; let txs_mempool = data.txs_mempool; let mut processed_txs = Vec::with_capacity(txs.len()); diff --git a/rust-libs/duniter-gva/src/queries.rs b/rust-libs/duniter-gva/src/queries.rs index e90afc4e4d4bd1044d3c52d6077efe8757cf2e3b..ea08f16cf0718da4cf608e49d62d9d49b882e598 100644 --- a/rust-libs/duniter-gva/src/queries.rs +++ b/rust-libs/duniter-gva/src/queries.rs @@ -19,6 +19,7 @@ pub mod uds; pub mod utxos; use crate::*; +use duniter_dbs::cm_v1::CmV1DbReadable as _; #[derive(async_graphql::MergedObject, Default)] pub struct QueryRoot( @@ -29,26 +30,39 @@ pub struct QueryRoot( queries::utxos::UtxosQuery, ); -#[derive(async_graphql::SimpleObject)] -struct Node { - /// Software - software: &'static str, - - /// Software version - version: &'static str, +#[derive(Default, async_graphql::SimpleObject)] +struct NodeQuery { + node: Node, } #[derive(Default)] -pub(crate) struct NodeQuery; +struct Node; #[async_graphql::Object] -impl NodeQuery { - /// Node informations - async fn node(&self, ctx: &async_graphql::Context<'_>) -> async_graphql::Result<Node> { +impl Node { + /// Peer card + async fn peer( + &self, + ctx: &async_graphql::Context<'_>, + ) -> async_graphql::Result<Option<PeerCardStringified>> { + let data = ctx.data::<SchemaData>()?; + + Ok(data + .dbs_pool + .execute(move |dbs| dbs.cm_db.self_peer_card().get(&EmptyKey)) + .await?? + .map(Into::into)) + } + /// Software + async fn software(&self) -> &'static str { + "duniter" + } + /// Software version + async fn version( + &self, + ctx: &async_graphql::Context<'_>, + ) -> async_graphql::Result<&'static str> { let data = ctx.data::<SchemaData>()?; - Ok(Node { - software: "duniter", - version: data.software_version, - }) + Ok(data.server_meta_data.software_version) } } diff --git a/rust-libs/duniter-gva/src/queries/gen_txs.rs b/rust-libs/duniter-gva/src/queries/gen_txs.rs index a8f25a7f3b4303ccfe32e082552703ad8f838bea..8889f7248bc6783355d8ef0b8c693ffdf3f86bd0 100644 --- a/rust-libs/duniter-gva/src/queries/gen_txs.rs +++ b/rust-libs/duniter-gva/src/queries/gen_txs.rs @@ -40,7 +40,7 @@ impl GenTxsQuery { let recipient = PublicKey::from_base58(&recipient)?; let data = ctx.data::<SchemaData>()?; - let currency = data.currency.clone(); + let currency = data.server_meta_data.currency.clone(); let (current_block, inputs, inputs_sum) = data .dbs_pool diff --git a/rust-libs/duniter-gva/src/schema.rs b/rust-libs/duniter-gva/src/schema.rs index 7d05600c6d86f1eb598dac3811331ca550e6eaa3..9618f6ee785bd8677fb54d5b73933c58c94e4cd7 100644 --- a/rust-libs/duniter-gva/src/schema.rs +++ b/rust-libs/duniter-gva/src/schema.rs @@ -21,10 +21,8 @@ pub(crate) type GraphQlSchema = async_graphql::Schema< crate::subscriptions::SubscriptionRoot, >; pub(crate) struct SchemaData { - pub(crate) currency: String, pub(crate) dbs: DuniterDbs, pub(crate) dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, - pub(crate) server_pubkey: PublicKey, - pub(crate) software_version: &'static str, + pub(crate) server_meta_data: ServerMetaData, pub(crate) txs_mempool: TxsMempool, } diff --git a/rust-libs/duniter-gva/src/warp_.rs b/rust-libs/duniter-gva/src/warp_.rs index 513fe5975969629feb2ae61a2dcfb1b8b0de78af..bc8aba0c7f28f8fa9ac5d2745f2fd9596c9cb40d 100644 --- a/rust-libs/duniter-gva/src/warp_.rs +++ b/rust-libs/duniter-gva/src/warp_.rs @@ -55,7 +55,7 @@ pub(crate) fn graphql( opts: async_graphql::http::MultipartOptions, ) -> impl warp::Filter<Extract = (impl warp::Reply,), Error = Rejection> + Clone { let opts = Arc::new(opts); - warp::path::path(conf.remote_path.clone()) + warp::path::path(conf.path.clone()) .and(warp::method()) .and(warp::query::raw().or(warp::any().map(String::new)).unify()) .and(warp::header::optional::<String>("content-type")) diff --git a/rust-libs/duniter-server/src/lib.rs b/rust-libs/duniter-server/src/lib.rs index 5b35c9d6d70be1e9f0d523ae1b683bd7fac15d6e..e99820f34fdbd0a49e55de3de1c58148a11883ba 100644 --- a/rust-libs/duniter-server/src/lib.rs +++ b/rust-libs/duniter-server/src/lib.rs @@ -23,10 +23,11 @@ )] pub use duniter_dbs::smallvec; +use duniter_gva::ServerMetaData; use duniter_mempools::{TxMpError, TxsMempool}; use fast_threadpool::ThreadPoolConfig; -pub use duniter_gva::GvaConf; +pub use duniter_gva::{GvaConf, PeerCardStringified}; use dubp::common::crypto::keys::ed25519::PublicKey; use dubp::common::prelude::*; @@ -34,6 +35,7 @@ use dubp::documents::{prelude::*, transaction::TransactionDocumentV10}; use dubp::{ block::prelude::*, common::crypto::hashs::Hash, documents_parser::prelude::FromStringObject, }; +use duniter_dbs::cm_v1::CmV1DbWritable; use duniter_dbs::{ kv_typed::prelude::*, GvaV1DbReadable, HashKeyV2, PendingTxDbV2, TxsMpV2DbReadable, }; @@ -51,7 +53,7 @@ pub enum DuniterCommand { #[derive(Clone, Debug)] pub struct DuniterServerConf { pub gva: Option<GvaConf>, - pub server_pubkey: PublicKey, + pub self_pubkey: PublicKey, pub txs_mempool_size: usize, } @@ -101,21 +103,16 @@ impl DuniterServer { fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs.clone()); if command != DuniterCommand::Sync { - if let Some(mut gva_conf) = conf.gva.clone() { - if let Some(remote_path) = std::env::var_os("DUNITER_GVA_REMOTE_PATH") { - gva_conf.remote_path( - remote_path - .into_string() - .expect("Invalid utf8 for Env var DUNITER_GVA_REMOTE_PATH"), - ); - } + if let Some(gva_conf) = conf.gva.clone() { duniter_gva::GvaServer::start( gva_conf, - currency, dbs, threadpool.async_handler(), - conf.server_pubkey, - software_version, + ServerMetaData { + currency, + self_pubkey: conf.self_pubkey, + software_version, + }, txs_mempool, ) .expect("Fail to start GVA server"); @@ -304,6 +301,27 @@ impl DuniterServer { }) .expect("dbs pool disconnected") } + pub fn update_self_peer(&self, new_peer_card: PeerCardStringified) { + self.dbs_pool + .execute(move |dbs| { + dbs.cm_db + .self_peer_card_write() + .upsert( + EmptyKey, + duniter_dbs::PeerCardDbV1 { + version: new_peer_card.version, + currency: new_peer_card.currency, + pubkey: new_peer_card.pubkey, + blockstamp: new_peer_card.blockstamp, + endpoints: new_peer_card.endpoints, + status: new_peer_card.status, + signature: new_peer_card.signature, + }, + ) + .expect("fail to write on memory db") + }) + .expect("dbs pool disconnected") + } } #[cfg(test)] @@ -318,7 +336,7 @@ mod tests { None, DuniterServerConf { gva: None, - server_pubkey: PublicKey::default(), + self_pubkey: PublicKey::default(), txs_mempool_size: 200, }, "currency_test".to_owned(), diff --git a/server.ts b/server.ts index 6cdd3e3dc5a2847aa3e442b8d4f673bb932c5f18..ca8e26559aa8b9f20b4b0184f4a750031b7be4bb 100644 --- a/server.ts +++ b/server.ts @@ -47,6 +47,7 @@ import {HttpMilestonePage} from "./app/modules/bma/lib/dtos" import * as toJson from "./app/modules/bma/lib/tojson" import { rawTxParseAndVerify, txVerify } from "./neon/lib" import { TransactionDTOV10 } from "./neon/native" +import { format } from "util"; export interface HookableServer { generatorGetJoinData: (...args:any[]) => Promise<any> @@ -352,7 +353,8 @@ export class Server extends stream.Duplex implements HookableServer { } async initDAL(conf:ConfDTO|null = null, commandName: string|null = null) { - await this.dal.init(this.conf, commandName) + this.genGvaEndpoints(this.conf); + await this.dal.init(this.conf, commandName); // Maintenance let head_1 = await this.dal.bindexDAL.head(1); if (head_1) { @@ -381,6 +383,36 @@ export class Server extends stream.Duplex implements HookableServer { await this.BlockchainService.forkResolution() } + genGvaEndpoint(conf: ConfDTO): string { + return "" + } + + genGvaSubscriptionsEndpoint(conf: ConfDTO): string { + return "" + } + + genGvaEndpoints(conf:ConfDTO) { + if (conf.gva) { + let gva = conf.gva; + this.addEndpointsDefinitions(async () => format( + "GVA %s%s %i %s", + (gva.remotePort === 443 || gva.remoteTls === true) ? 'S ':'', + gva.remoteHost || gva.host || "localhost", + gva.remotePort || gva.port || 80, + gva.remotePath || gva.path || "" + )); + if (gva.remoteSubscriptionsPath || gva.subscriptionsPath) { + this.addEndpointsDefinitions(async () => format( + "GVASUB %s%s %i %s", + (gva.remotePort === 443 || gva.remoteTls === true) ? 'S ':'', + gva.remoteHost || gva.host || "localhost", + gva.remotePort || gva.port || 80, + gva.remoteSubscriptionsPath || gva.subscriptionsPath || "" + )); + } + } + } + recomputeSelfPeer(): Promise<DBPeer | null> { return this.PeeringService.generateSelfPeer(this.conf) }