Skip to content

Commit

Permalink
feat: upgrade to new workspace (workspace — requires tweaks) (#7)
Browse files Browse the repository at this point in the history
* feat: upgrade to new workspace (workspace — requires tweaks)

* feat: Use latest workspace. Workspace needs tweaks still

* feat: compiling tests

* fix: RPC port fmt error

* chore: update to main branch of sdk
  • Loading branch information
tbraun96 authored Feb 10, 2025
1 parent 6e53945 commit edb1099
Show file tree
Hide file tree
Showing 11 changed files with 198 additions and 254 deletions.
25 changes: 10 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,32 @@ edition = "2021"

[package.metadata.blueprint]
manager = { Evm = "WstsBlueprint" }
master_revision = "Latest"

[dependencies]
gadget-sdk = { git = "https://github.com/tangle-network/gadget/", features = ["std"] }
#gadget-sdk = { path = "../gadget/sdk", features = ["std"] }
# Gadget dependencies
blueprint-sdk = { git = "https://github.com/tangle-network/gadget-workspace/", features = ["tangle", "local-store", "macros", "networking", "round-based-compat"] }
gadget-macros = { git = "https://github.com/tangle-network/gadget-workspace/" }
color-eyre = { version = "0.6", features = ["tracing-error", "color-spantrace"] }
tokio = { version = "1.40", default-features = false, features = ["full"] }
hex = { version = "0.4.3", default-features = false }
k256 = { version = "0.13.3", default-features = false }
bincode = "1.3.3"
sp-core = { version = "31.0.0", default-features = false }
rand_chacha = "0.3.1"
serde = { version = "1.0.214", features = ["derive"] }
round-based = { version = "0.3.2", features = ["runtime-tokio"] }
tracing-subscriber = "0.3.18"
serde = { version = "1.0.214", features = ["derive", "rc"] }
round-based = { version = "0.3.2", features = ["runtime-tokio", "derive", "round-based-derive"] }
thiserror = "2.0.3"
itertools = "0.13.0"
rand = "0.8.5"
parking_lot = { version = "0.12.3", features = ["serde"]}
p256k1 = "5.4"
frost-taproot = { git = "https://github.com/webb-tools/tangle.git", branch = "main", default-features = false}
p256k1 = "^5"
frost-secp256k1-tr = { git = "https://github.com/webb-tools/tangle.git", branch = "main", features = ["std"]}

# MPC specific deps
wsts = "3.0.0"

[build-dependencies]
blueprint-metadata = { git = "https://github.com/tangle-network/gadget/" }
blueprint-build-utils = { git = "https://github.com/tangle-network/gadget/" }
blueprint-sdk = { git = "https://github.com/tangle-network/gadget-workspace/", features = ["build"] }

[dev-dependencies]
blueprint-test-utils = { git = "https://github.com/tangle-network/gadget/" }
cargo-tangle = { git = "https://github.com/tangle-network/gadget/" }
blueprint-sdk = { git = "https://github.com/tangle-network/gadget-workspace/", features = ["testing"] }

[features]
default = ["std"]
Expand Down
6 changes: 4 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use blueprint_sdk::build::blueprint_metadata;

fn main() {
println!("cargo:rerun-if-changed=src/lib.rs");
println!("cargo:rerun-if-changed=src/main.rs");
blueprint_metadata::generate_json();

let contract_dirs: Vec<&str> = vec!["./contracts"];
blueprint_build_utils::soldeer_update();
blueprint_build_utils::build_contracts(contract_dirs);
blueprint_sdk::build::utils::soldeer_update();
blueprint_sdk::build::utils::build_contracts(contract_dirs);
}
29 changes: 15 additions & 14 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
use crate::keygen_state_machine::WstsState;
use blueprint_sdk::config::StdGadgetConfiguration;
use blueprint_sdk::macros::contexts::{
KeystoreContext, P2pContext, ServicesContext, TangleClientContext,
};
use blueprint_sdk::networking::networking::NetworkMultiplexer;
use blueprint_sdk::networking::setup::start_p2p_network;
use blueprint_sdk::networking::GossipMsgKeyPair;
use blueprint_sdk::stores::local_database::LocalDatabase;
use color_eyre::eyre;
use gadget_sdk as sdk;
use gadget_sdk::ext::subxt::tx::Signer;
use gadget_sdk::network::NetworkMultiplexer;
use gadget_sdk::store::LocalDatabase;
use gadget_sdk::subxt_core::ext::sp_core::ecdsa;
use sdk::contexts::{KeystoreContext, MPCContext, ServicesContext, TangleClientContext};
use std::path::PathBuf;
use std::sync::Arc;

use crate::keygen_state_machine::WstsState;

/// The network protocol version for the WSTS service
const NETWORK_PROTOCOL: &str = "/wsts/frost/1.0.0";

/// WSTS Service Context that holds all the necessary context for the service
/// to run. This structure implements various traits for keystore, client, and service
/// functionality.
#[derive(Clone, KeystoreContext, TangleClientContext, ServicesContext, MPCContext)]
#[derive(Clone, KeystoreContext, TangleClientContext, ServicesContext, P2pContext)]
pub struct WstsContext {
#[config]
pub config: sdk::config::StdGadgetConfiguration,
pub config: StdGadgetConfiguration,
#[call_id]
pub call_id: Option<u64>,
pub network_backend: Arc<NetworkMultiplexer>,
pub store: Arc<LocalDatabase<WstsState>>,
pub identity: ecdsa::Pair,
pub identity: GossipMsgKeyPair,
}

// Core context management implementation
Expand All @@ -35,13 +36,13 @@ impl WstsContext {
/// Returns an error if:
/// - Network initialization fails
/// - Configuration is invalid
pub fn new(config: sdk::config::StdGadgetConfiguration) -> eyre::Result<Self> {
pub fn new(config: StdGadgetConfiguration) -> eyre::Result<Self> {
let network_config = config
.libp2p_network_config(NETWORK_PROTOCOL)
.map_err(|err| eyre::eyre!("Failed to create network configuration: {err}"))?;

let identity = network_config.ecdsa_key.clone();
let gossip_handle = sdk::network::setup::start_p2p_network(network_config)
let identity = network_config.secret_key.clone();
let gossip_handle = start_p2p_network(network_config)
.map_err(|err| eyre::eyre!("Failed to start the P2P network: {err}"))?;

let keystore_dir = PathBuf::from(config.keystore_uri.clone()).join("wsts.json");
Expand Down
65 changes: 34 additions & 31 deletions src/keygen.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use crate::keygen_state_machine;
use crate::utils::validate_parameters;
use crate::{context::WstsContext, keygen_state_machine::WstsState};
use gadget_sdk::contexts::MPCContext;
use gadget_sdk::{
event_listener::tangle::{
jobs::{services_post_processor, services_pre_processor},
TangleEventListener,
},
job,
network::round_based_compat::NetworkDeliveryWrapper,
tangle_subxt::tangle_testnet_runtime::api::services::events::JobCalled,
Error as GadgetError,
use blueprint_sdk::crypto::k256::K256VerifyingKey;
use blueprint_sdk::crypto::KeyEncoding;
use blueprint_sdk::event_listeners::tangle::events::TangleEventListener;
use blueprint_sdk::event_listeners::tangle::services::{
services_post_processor, services_pre_processor,
};
use sp_core::ecdsa::Public;
use blueprint_sdk::job;
use blueprint_sdk::logging::info;
use blueprint_sdk::macros::ext::contexts::tangle::TangleClientContext;
use blueprint_sdk::networking::round_based_compat::NetworkDeliveryWrapper;
use blueprint_sdk::tangle_subxt::tangle_testnet_runtime::api::services::events::JobCalled;
use gadget_macros::ext::clients::GadgetServicesClient;
use std::collections::BTreeMap;
use wsts::v2::Party;

Expand Down Expand Up @@ -40,36 +40,42 @@ use wsts::v2::Party;
/// - Failed to get party information
/// - MPC protocol execution failed
/// - Serialization of results failed
pub async fn keygen(t: u16, context: WstsContext) -> Result<Vec<u8>, GadgetError> {
pub async fn keygen(t: u16, context: WstsContext) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
// Get configuration and compute deterministic values
let blueprint_id = context
let client = context.tangle_client().await?;
let blueprint_id = client
.blueprint_id()
.map_err(|e| KeygenError::ContextError(e.to_string()))?;
let call_id = context
.current_call_id()
.await
.map_err(|e| KeygenError::ContextError(e.to_string()))?;
let call_id = context
.call_id
.ok_or_else(|| KeygenError::ContextError("Call_id not set".into()))?;

// Setup party information
let (i, operators) = context
let (i, operators) = client
.get_party_index_and_operators()
.await
.map_err(|e| KeygenError::ContextError(e.to_string()))?;

let parties: BTreeMap<u16, Public> = operators
let parties: BTreeMap<u16, _> = operators
.into_iter()
.enumerate()
.map(|(j, (_, ecdsa))| (j as u16, ecdsa))
.map(|(j, (_, ecdsa))| {
(
j as u16,
K256VerifyingKey::from_bytes(&ecdsa.0).expect("33 byte compressed ECDSA key"),
)
})
.collect();

let n = parties.len() as u16;
let i = i as u16;
let k = n;

let (meta_hash, deterministic_hash) =
crate::compute_deterministic_hashes(n, blueprint_id, call_id, KEYGEN_SALT);
crate::compute_execution_hashes(n, blueprint_id, call_id, KEYGEN_SALT);

gadget_sdk::info!(
info!(
"Starting WSTS Keygen for party {i}, n={n}, eid={}",
hex::encode(deterministic_hash)
);
Expand All @@ -83,7 +89,7 @@ pub async fn keygen(t: u16, context: WstsContext) -> Result<Vec<u8>, GadgetError

let state = protocol(n as _, i as _, k as _, t as _, network).await?;

gadget_sdk::info!(
info!(
"Ending WSTS Keygen for party {i}, n={n}, eid={}",
hex::encode(deterministic_hash)
);
Expand Down Expand Up @@ -113,12 +119,9 @@ pub enum KeygenError {

#[error("Delivery error: {0}")]
DeliveryError(String),
}

impl From<KeygenError> for GadgetError {
fn from(err: KeygenError) -> Self {
GadgetError::Other(err.to_string())
}
#[error("Setup error: {0}")]
SetupError(String),
}

async fn protocol(
Expand All @@ -127,7 +130,7 @@ async fn protocol(
k: u32,
t: u32,
network: NetworkDeliveryWrapper<keygen_state_machine::Msg>,
) -> Result<WstsState, GadgetError> {
) -> Result<WstsState, KeygenError> {
validate_parameters(n, k, t)?;
let mut rng = rand::rngs::OsRng;
let key_ids = crate::utils::generate_party_key_ids(n, k);
Expand All @@ -138,9 +141,9 @@ async fn protocol(
let network = round_based::party::MpcParty::connected(network);
let mut party = Party::new(party_id, our_key_ids, n, k, t, &mut rng);
let state =
crate::keygen_state_machine::wsts_protocol(network, &mut party, n as usize, &mut rng)
.await?;
gadget_sdk::info!(
keygen_state_machine::wsts_protocol(network, &mut party, n as usize, &mut rng).await?;

info!(
"Combined public key: {:?}",
state.party.lock().as_ref().unwrap().group_key
);
Expand Down
13 changes: 8 additions & 5 deletions src/keygen_state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use serde::{Deserialize, Serialize};
use std::collections::HashMap;

use crate::keygen::KeygenError;
use frost_taproot::VerifyingKey;
use blueprint_sdk::logging::{info, trace};
use frost_secp256k1_tr::VerifyingKey;
use itertools::Itertools;
use round_based::SinkExt;
use std::sync::Arc;
Expand Down Expand Up @@ -99,7 +100,7 @@ where
state.poly_commitments.insert(party_id, msg.poly_commitment);
}

gadget_sdk::trace!(
trace!(
"Received shares: {:?}",
state.shares.keys().collect::<Vec<_>>()
);
Expand All @@ -119,6 +120,7 @@ where
(key_id, key_shares.into_iter().collect())
})
.collect();

let polys = state
.poly_commitments
.iter()
Expand All @@ -135,14 +137,15 @@ where
// Convert the WSTS group key into a FROST-compatible format
let group_point = party.group_key;
let compressed_group_point = group_point.compress();
let verifying_key = VerifyingKey::deserialize(compressed_group_point.data).map_err(|e| {
let verifying_key = VerifyingKey::deserialize(&compressed_group_point.data).map_err(|e| {
KeygenError::MpcError(format!("Failed to convert group key to VerifyingKey: {e}"))
})?;
let public_key_frost_format = verifying_key.serialize().as_ref().to_vec();

let public_key_frost_format = verifying_key.serialize().expect("Failed to serialize key");
state.public_key_frost_format = public_key_frost_format;
state.party = Arc::new(parking_lot::Mutex::new(Some(party)));

gadget_sdk::info!("Keygen finished computing secret");
info!("Keygen finished computing secret");

Ok(state)
}
Expand Down
28 changes: 23 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,44 @@ pub mod keygen;
pub(crate) mod keygen_state_machine;
pub mod signing;
pub(crate) mod signing_state_machine;
pub(crate) mod utils;
pub mod utils;

pub use blueprint_sdk::*;

const META_SALT: &str = "wsts-protocol";

#[macro_export]
macro_rules! compute_sha256_hash {
($($data:expr),*) => {
{
use k256::sha2::{Digest, Sha256};
let mut hasher = Sha256::default();
$(hasher.update($data);)*
let result = hasher.finalize();
let mut hash = [0u8; 32];
hash.copy_from_slice(result.as_slice());
hash
}
};
}

/// Helper function to compute deterministic hashes for the WSTS processes.
/// Note: for signing, the "call_id" should be the call_id of the preceeding
/// keygen job
pub fn compute_deterministic_hashes(
pub fn compute_execution_hashes(
n: u16,
blueprint_id: u64,
call_id: u64,
salt: &'static str,
) -> ([u8; 32], [u8; 32]) {
let meta_hash = gadget_sdk::compute_sha256_hash!(
let interexecution_hash = compute_sha256_hash!(
n.to_be_bytes(),
blueprint_id.to_be_bytes(),
call_id.to_be_bytes(),
META_SALT
);

let deterministic_hash = gadget_sdk::compute_sha256_hash!(meta_hash.as_ref(), salt);
let intraexecution_hash = compute_sha256_hash!(interexecution_hash.as_ref(), salt);

(meta_hash, deterministic_hash)
(interexecution_hash, intraexecution_hash)
}
13 changes: 7 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use blueprint_sdk::logging::info;
use blueprint_sdk::macros;
use blueprint_sdk::runners::core::runner::BlueprintRunner;
use blueprint_sdk::runners::tangle::tangle::TangleConfig;
use color_eyre::Result;
use gadget_sdk::info;
use gadget_sdk::runners::tangle::TangleConfig;
use gadget_sdk::runners::BlueprintRunner;
use gadget_sdk::subxt::ext::sp_core::Pair;
use wsts_blueprint::context::WstsContext;
use wsts_blueprint::crypto::KeyEncoding;

#[gadget_sdk::main(env)]
#[macros::main(env)]
async fn main() {
let context = WstsContext::new(env.clone())?;

info!(
"Starting the Blueprint Runner for {} ...",
hex::encode(context.identity.public().as_ref())
hex::encode(context.identity.public().to_bytes())
);

info!("~~~ Executing the WSTS blueprint ~~~");
Expand Down
Loading

0 comments on commit edb1099

Please sign in to comment.