Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: mock service to serve dependencies #406

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
282 changes: 156 additions & 126 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["common", "config", "service", "tap-agent"]
members = ["common", "config", "local-service", "service", "tap-agent"]
resolver = "2"

[profile.dev.package."*"]
Expand Down Expand Up @@ -35,6 +35,7 @@ sqlx = { version = "0.8.2", features = [
"runtime-tokio",
"rust_decimal",
], default-features = false }
toml = { version = "0.8.19", default-features = false }
tracing = { version = "0.1.40", default-features = false }
bigdecimal = "0.4.3"
build-info = "0.0.39"
Expand Down
4 changes: 2 additions & 2 deletions common/src/allocations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use alloy::primitives::U256;
use serde::{Deserialize, Deserializer};
use serde::{Deserialize, Deserializer, Serialize};
use thegraph_core::{Address, DeploymentId};

pub mod monitor;
Expand Down Expand Up @@ -33,7 +33,7 @@ pub enum AllocationStatus {
Claimed,
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct SubgraphDeployment {
pub id: DeploymentId,
#[serde(rename = "deniedAt")]
Expand Down
4 changes: 2 additions & 2 deletions common/src/attestations/signers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn attestation_signers(
dispute_manager_rx,
move |(allocation, dispute)| {
let indexer_mnemonic = indexer_mnemonic.clone();
modify_sigers(
modify_signers(
&indexer_mnemonic,
chain_id,
attestation_signers_map,
Expand All @@ -39,7 +39,7 @@ pub fn attestation_signers(
},
)
}
fn modify_sigers(
fn modify_signers(
indexer_mnemonic: &str,
chain_id: ChainId,
attestation_signers_map: &'static Mutex<HashMap<Address, AttestationSigner>>,
Expand Down
2 changes: 1 addition & 1 deletion config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ regex = "1.11.0"
sealed_test = "1.1.0"
serde_test = "1.0.177"
tempfile = "3.10.1"
toml = { version = "0.8.12", default-features = false }
toml.workspace = true
tracing-test = "0.2.5"
28 changes: 28 additions & 0 deletions local-service/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
# SPDX-License-Identifier: Apache-2.0

[package]
name = "local-service"
version = "0.1.0"
edition = "2021"

[[bin]]
name = "local-service"
path = "src/main.rs"

[lib]
path = "src/lib.rs"

[dependencies]
alloy = { workspace = true, features = ["k256"] }
anyhow.workspace = true
axum = { version = "0.7.5", features = ["macros"] }
indexer-common = { path = "../common" }
dotenvy = "0.15.7"
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
thegraph-core.workspace = true
tokio = { workspace = true, features = ["full"] }
toml.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
70 changes: 70 additions & 0 deletions local-service/src/allocations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

use indexer_common::prelude::SubgraphDeployment;
use serde::{Deserialize, Serialize};

use crate::{bootstrap::CREATED_AT_BLOCK_HASH, keys::Signer};

#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct Allocations {
meta: Meta,
allocations: Vec<AllocationFragment>,
}

impl Allocations {
pub fn new(indexer: Signer) -> Self {
Allocations {
meta: Meta {
block: Block {
number: 123,
hash: CREATED_AT_BLOCK_HASH.into(),
timestamp: "2021-01-01T00:00:00Z".into(),
},
},
allocations: vec![AllocationFragment {
id: indexer.allocation.id.to_string(),
indexer: Indexer {
id: indexer.allocation.indexer.to_string(),
},
allocated_tokens: indexer.allocation.allocated_tokens.to_string(),
created_at_block_hash: indexer.allocation.created_at_block_hash,
created_at_epoch: indexer.allocation.created_at_epoch.to_string(),
closed_at_epoch: indexer
.allocation
.closed_at_epoch
.map(|epoch| epoch.to_string()),
subgraph_deployment: indexer.allocation.subgraph_deployment,
}],
}
}
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct AllocationFragment {
id: String,
indexer: Indexer,
allocated_tokens: String,
created_at_block_hash: String,
created_at_epoch: String,
closed_at_epoch: Option<String>,
subgraph_deployment: SubgraphDeployment,
}

#[derive(Debug, Serialize, Deserialize)]
struct Indexer {
id: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Meta {
block: Block,
}

#[derive(Debug, Serialize, Deserialize)]
struct Block {
number: u128,
hash: String,
timestamp: String,
}
98 changes: 98 additions & 0 deletions local-service/src/bootstrap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

use alloy::primitives::B256;
use axum::{
http::StatusCode,
response::IntoResponse,
routing::{get, post},
Router,
};
use indexer_common::prelude::{
Allocation, AllocationStatus, AttestationSigner, SubgraphDeployment,
};
use thegraph_core::{address, Address, DeploymentId};
use tokio::net::TcpListener;
use tracing::info;

use crate::{
keys::{get_indexer_address_from_toml, get_mnemonic_from_toml, Signer},
subgraph::{network_subgraph, NETWORK_SUBGRAPH_ROUTE},
};

const HOST: &str = "0.0.0.0";
const PORT: &str = "8000";
pub const CREATED_AT_BLOCK_HASH: &str =
"0x0000000000000000000000000000000000000000000000000000000000000000";

pub async fn start_server() -> anyhow::Result<()> {
let signer = Config::signer()?;
info!("Starting server on {HOST}:{PORT}");
let port = dotenvy::var("API_PORT").unwrap_or(PORT.into());
let listener = TcpListener::bind(&format!("{HOST}:{port}")).await?;

let router = Router::new().route("/health", get(health_check)).route(
NETWORK_SUBGRAPH_ROUTE,
post(move || network_subgraph(signer)),
);

Ok(axum::serve(listener, router).await?)
}

async fn health_check() -> impl IntoResponse {
StatusCode::OK
}

struct Config;

impl Config {
fn signer() -> anyhow::Result<Signer> {
let mnemonic = get_mnemonic_from_toml("indexer", "operator_mnemonic")?;
let indexer_address = get_indexer_address_from_toml("indexer", "indexer_address")?;

let subgraph_deployment_id =
Self::create_deployment_id("QmUhiH6Z5xo6o3GNzsSvqpGKLmCt6w5A")?;

let subgraph_deployment = SubgraphDeployment {
id: DeploymentId::new(B256::from(subgraph_deployment_id)),
denied_at: None,
};

let allocation = Self::create_allocation(subgraph_deployment, indexer_address)?;

let dispute_address = address!("33f9E93266ce0E108fc85DdE2f71dab555A0F05a");

let signer = Signer::new(
AttestationSigner::new(&mnemonic, &allocation, 42161, dispute_address)?,
allocation,
);

Ok(signer)
}

fn create_deployment_id(deployment_str: &str) -> anyhow::Result<[u8; 32]> {
let id: [u8; 32] = deployment_str.as_bytes().try_into()?;
Ok(id)
}

fn create_allocation(
subgraph_deployment: SubgraphDeployment,
indexer_address: Address,
) -> anyhow::Result<Allocation> {
Ok(Allocation {
id: address!("5BcFE6215cbeB2D75cc3b09e01243cd7Ac55B3a7"),
status: AllocationStatus::Active,
subgraph_deployment,
indexer: indexer_address,
allocated_tokens: Default::default(),
created_at_epoch: 1,
created_at_block_hash: CREATED_AT_BLOCK_HASH.into(),
closed_at_epoch: None,
closed_at_epoch_start_block_hash: None,
previous_epoch_start_block_hash: None,
poi: None,
query_fee_rebates: None,
query_fees_collected: None,
})
}
}
61 changes: 61 additions & 0 deletions local-service/src/keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

#![allow(dead_code)]

use std::{io, path::PathBuf};

use alloy::primitives::Address;
use indexer_common::prelude::{Allocation, AttestationSigner};
use toml::Value;

#[derive(Clone, Debug)]
pub struct Signer {
pub signer: AttestationSigner,
pub allocation: Allocation,
}

impl Signer {
pub fn new(signer: AttestationSigner, allocation: Allocation) -> Self {
Signer { signer, allocation }
}
}

pub fn get_mnemonic_from_toml(index: &str, key: &str) -> io::Result<String> {
Ok(get_from_toml(index, key)?.to_string())
}

pub fn get_indexer_address_from_toml(index: &str, key: &str) -> io::Result<Address> {
Ok(get_from_toml(index, key)?.parse().unwrap())
}

fn get_from_toml(index: &str, key: &str) -> io::Result<String> {
let toml = get_value_from_toml().unwrap();

if let Some(item) = toml
.get(index)
.and_then(|index| index.get(key))
.and_then(|value| value.as_str())
{
Ok(item.to_string())
} else {
Err(io::Error::new(
io::ErrorKind::Other,
"Config item not found in TOML file",
))
}
}

fn get_value_from_toml() -> io::Result<Value> {
let config_path = get_config_path();
let content = std::fs::read_to_string(config_path)?;
let toml: Value = content.parse().unwrap();
Ok(toml)
}

fn get_config_path() -> PathBuf {
// CARGO_MANIFEST_DIR points to the root of the current crate
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("config.toml"); // Add the file name
path
}
7 changes: 7 additions & 0 deletions local-service/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

mod allocations;
pub mod bootstrap;
mod keys;
mod subgraph;
17 changes: 17 additions & 0 deletions local-service/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

use std::process::ExitCode;

use local_service::bootstrap::start_server;

#[tokio::main]
async fn main() -> ExitCode {
tracing_subscriber::fmt::init();

if let Err(e) = start_server().await {
tracing::error!("Local Service error: {e}");
return ExitCode::from(1);
}
ExitCode::SUCCESS
}
18 changes: 18 additions & 0 deletions local-service/src/subgraph.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

use axum::{response::IntoResponse, Json};
use serde::{Deserialize, Serialize};

use crate::{allocations::Allocations, keys::Signer};

pub(crate) const NETWORK_SUBGRAPH_ROUTE: &str = "/network_subgraph";

pub(crate) async fn network_subgraph(indexer: Signer) -> impl IntoResponse {
Json(GraphqlResponse::Allocations(Allocations::new(indexer)))
}

#[derive(Debug, Serialize, Deserialize)]
pub(crate) enum GraphqlResponse {
Allocations(Allocations),
}
Loading