Skip to content

Commit

Permalink
Merge 576561f into 6a3f554
Browse files Browse the repository at this point in the history
  • Loading branch information
Jannis committed Oct 17, 2023
2 parents 6a3f554 + 576561f commit 0c7f7af
Show file tree
Hide file tree
Showing 15 changed files with 660 additions and 904 deletions.
36 changes: 36 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ anyhow = "1.0.75"
arc-swap = "1.6.0"
ethers = "2.0.10"
ethers-core = "2.0.10"
eventuals = "0.6.7"
faux = { version = "0.1.10", optional = true }
keccak-hash = "0.10.0"
lazy_static = "1.4.0"
log = "0.4.20"
lru = "0.11.1"
regex = "1.7.1"
reqwest = "0.11.20"
secp256k1 = { version = "0.27.0", features = ["recovery"] }
Expand Down
182 changes: 5 additions & 177 deletions common/src/allocations/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
// Copyright 2023-, GraphOps and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

use alloy_primitives::{Address, B256};
use anyhow::Result;
use ethers::signers::coins_bip39::English;
use ethers::signers::{MnemonicBuilder, Signer, Wallet};
use ethers_core::k256::ecdsa::SigningKey;
use alloy_primitives::Address;
use ethers_core::types::U256;
use serde::Deserialize;
use serde::Deserializer;
use serde::{Deserialize, Deserializer};
use toolshed::thegraph::DeploymentId;

pub mod monitor;

#[derive(Debug, Eq, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Allocation {
pub id: Address,
pub status: AllocationStatus,
Expand All @@ -30,7 +25,7 @@ pub struct Allocation {
pub query_fees_collected: Option<U256>,
}

#[derive(Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum AllocationStatus {
Null,
Active,
Expand All @@ -39,21 +34,8 @@ pub enum AllocationStatus {
Claimed,
}

// Custom deserializer for `DeploymentId` that accepts a `0x...` string
fn deserialize_deployment_id<'de, D>(deserializer: D) -> Result<DeploymentId, D::Error>
where
D: Deserializer<'de>,
{
let bytes = B256::deserialize(deserializer)?;
Ok(DeploymentId(bytes))
}

#[derive(Debug, Eq, PartialEq, Deserialize)]
#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
pub struct SubgraphDeployment {
// This neeeds a custom deserialize function because it's returned from the
// network subgraph as a hex string but `DeploymentId` assumes an IPFS hash
// in it's `Deserialize` implementation
#[serde(deserialize_with = "deserialize_deployment_id")]
pub id: DeploymentId,
#[serde(rename = "deniedAt")]
pub denied_at: Option<u64>,
Expand Down Expand Up @@ -106,157 +88,3 @@ impl<'d> Deserialize<'d> for Allocation {
})
}
}

pub fn derive_key_pair(
indexer_mnemonic: &str,
epoch: u64,
deployment: &DeploymentId,
index: u64,
) -> Result<Wallet<SigningKey>> {
let mut derivation_path = format!("m/{}/", epoch);
derivation_path.push_str(
&deployment
.to_string()
.as_bytes()
.iter()
.map(|char| char.to_string())
.collect::<Vec<String>>()
.join("/"),
);
derivation_path.push_str(format!("/{}", index).as_str());

Ok(MnemonicBuilder::<English>::default()
.derivation_path(&derivation_path)
.expect("Valid derivation path")
.phrase(indexer_mnemonic)
.build()?)
}

pub fn allocation_signer(indexer_mnemonic: &str, allocation: &Allocation) -> Result<SigningKey> {
// Guess the allocation index by enumerating all indexes in the
// range [0, 100] and checking for a match
for i in 0..100 {
// The allocation was either created at the epoch it intended to or one
// epoch later. So try both both.
for created_at_epoch in [allocation.created_at_epoch, allocation.created_at_epoch - 1] {
let allocation_wallet = derive_key_pair(
indexer_mnemonic,
created_at_epoch,
&allocation.subgraph_deployment.id,
i,
)?;
if allocation_wallet.address().as_fixed_bytes() == allocation.id {
return Ok(allocation_wallet.signer().clone());
}
}
}
Err(anyhow::anyhow!(
"Could not find allocation signer for allocation {}",
allocation.id
))
}

#[cfg(test)]
mod test {
use lazy_static::lazy_static;
use std::str::FromStr;
use toolshed::thegraph::DeploymentId;

use super::*;

const INDEXER_OPERATOR_MNEMONIC: &str = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";

lazy_static! {
static ref DEPLOYMENT_ID: DeploymentId = DeploymentId(
"0xbbde25a2c85f55b53b7698b9476610c3d1202d88870e66502ab0076b7218f98a"
.parse()
.unwrap(),
);
}

#[test]
fn test_derive_key_pair() {
assert_eq!(
derive_key_pair(INDEXER_OPERATOR_MNEMONIC, 953, &DEPLOYMENT_ID, 0)
.unwrap()
.address()
.as_fixed_bytes(),
Address::from_str("0xfa44c72b753a66591f241c7dc04e8178c30e13af").unwrap()
);

assert_eq!(
derive_key_pair(INDEXER_OPERATOR_MNEMONIC, 940, &DEPLOYMENT_ID, 2)
.unwrap()
.address()
.as_fixed_bytes(),
Address::from_str("0xa171cd12c3dde7eb8fe7717a0bcd06f3ffa65658").unwrap()
);
}

#[test]
fn test_allocation_signer() {
// Note that we use `derive_key_pair` to derive the private key

let allocation = Allocation {
id: Address::from_str("0xa171cd12c3dde7eb8fe7717a0bcd06f3ffa65658").unwrap(),
status: AllocationStatus::Null,
subgraph_deployment: SubgraphDeployment {
id: *DEPLOYMENT_ID,
denied_at: None,
staked_tokens: U256::zero(),
signalled_tokens: U256::zero(),
query_fees_amount: U256::zero(),
},
indexer: Address::ZERO,
allocated_tokens: U256::zero(),
created_at_epoch: 940,
created_at_block_hash: "".to_string(),
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,
};
assert_eq!(
allocation_signer(INDEXER_OPERATOR_MNEMONIC, &allocation).unwrap(),
*derive_key_pair(
INDEXER_OPERATOR_MNEMONIC,
940,
&allocation.subgraph_deployment.id,
2
)
.unwrap()
.signer()
);
}

#[test]
fn test_allocation_signer_error() {
// Note that because allocation will try 200 derivations paths, this is a slow test

let allocation = Allocation {
// Purposefully wrong address
id: Address::from_str("0xdeadbeefcafebabedeadbeefcafebabedeadbeef").unwrap(),
status: AllocationStatus::Null,
subgraph_deployment: SubgraphDeployment {
id: *DEPLOYMENT_ID,
denied_at: None,
staked_tokens: U256::zero(),
signalled_tokens: U256::zero(),
query_fees_amount: U256::zero(),
},
indexer: Address::ZERO,
allocated_tokens: U256::zero(),
created_at_epoch: 940,
created_at_block_hash: "".to_string(),
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,
};
assert!(allocation_signer(INDEXER_OPERATOR_MNEMONIC, &allocation).is_err());
}
}
Loading

0 comments on commit 0c7f7af

Please sign in to comment.