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

feat(sig): sig use worker keypair if called in worker scope [NET-371] #1455

Merged
merged 14 commits into from
Feb 14, 2023
Merged
2 changes: 2 additions & 0 deletions Cargo.lock

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

7 changes: 7 additions & 0 deletions crates/key-manager/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

use libp2p::PeerId;
use std::path::PathBuf;
use thiserror::Error;

Expand Down Expand Up @@ -51,3 +52,9 @@ pub enum PersistedKeypairError {
err: std::io::Error,
},
}

#[derive(Debug, Error)]
pub enum KeyManagerError {
#[error("Keypair for peer_id {0} not found")]
KeypairNotFound(PeerId),
}
13 changes: 10 additions & 3 deletions crates/key-manager/src/key_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@
use fluence_keypair::{KeyFormat, KeyPair};
use libp2p::PeerId;
use std::collections::HashMap;
use std::ops::Range;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;

use crate::error::PersistedKeypairError;
use crate::error::{KeyManagerError, PersistedKeypairError};
use crate::persistence::{load_persisted_keypairs, persist_keypair, PersistedKeypair};
use parking_lot::RwLock;

pub const INSECURE_KEYPAIR_SEED: Range<u8> = 0..32;

#[derive(Clone)]
pub struct KeyManager {
/// scope_peer_id -> scope_keypair
Expand All @@ -33,6 +36,8 @@ pub struct KeyManager {
scope_peer_ids: Arc<RwLock<HashMap<PeerId, PeerId>>>,
keypairs_dir: PathBuf,
host_peer_id: PeerId,
// temporary public, will refactor
pub insecure_keypair: KeyPair,
}

impl KeyManager {
Expand All @@ -42,6 +47,8 @@ impl KeyManager {
scope_peer_ids: Arc::new(Default::default()),
keypairs_dir,
host_peer_id,
insecure_keypair: KeyPair::from_secret_key(INSECURE_KEYPAIR_SEED.collect(), KeyFormat::Ed25519)
.expect("error creating insecure keypair"),
};

this.load_persisted_keypairs();
Expand Down Expand Up @@ -105,12 +112,12 @@ impl KeyManager {
}
}

pub fn get_scope_keypair(&self, scope_peer_id: PeerId) -> eyre::Result<KeyPair> {
pub fn get_scope_keypair(&self, scope_peer_id: PeerId) -> Result<KeyPair, KeyManagerError> {
self.scope_keypairs
.read()
.get(&scope_peer_id)
.cloned()
.ok_or_else(|| eyre::eyre!("Keypair for peer id {} not found", scope_peer_id))
.ok_or(KeyManagerError::KeypairNotFound(scope_peer_id))
}

pub fn generate_keypair(&self) -> KeyPair {
Expand Down
2 changes: 2 additions & 0 deletions crates/key-manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ mod error;
mod key_manager;
mod persistence;

pub use error::KeyManagerError;
pub use key_manager::KeyManager;
pub use key_manager::INSECURE_KEYPAIR_SEED;
1 change: 1 addition & 0 deletions crates/particle-node-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ script-storage = { workspace = true }
aquamarine = { workspace = true }
sorcerer = { workspace = true }
fluence-keypair = { workspace = true }
key-manager = { workspace = true }
fluence-libp2p = { workspace = true }
humantime-serde = "1.1.1"

Expand Down
63 changes: 60 additions & 3 deletions crates/particle-node-tests/tests/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use std::str::FromStr;
use std::time::Duration;

use eyre::{Report, WrapErr};
use fluence_keypair::{KeyPair, Signature};
use fluence_keypair::{KeyFormat, KeyPair, Signature};
use itertools::Itertools;
use libp2p::core::Multiaddr;
use libp2p::kad::kbucket::Key;
Expand All @@ -39,6 +39,7 @@ use created_swarm::{
use fluence_libp2p::RandomPeerId;
use fluence_libp2p::Transport;
use json_utils::into_array;
use key_manager::INSECURE_KEYPAIR_SEED;
use now_millis::now_ms;
use particle_protocol::Particle;
use service_modules::load_module;
Expand Down Expand Up @@ -1436,8 +1437,8 @@ fn sign_invalid_tetraplets() {
client.receive_args().unwrap().as_slice()
{
assert!(host_error.contains(&format!("data is expected to be produced by service 'registry' on peer '{relay}', was from peer '{wrong_peer}'")));
assert!(srv_error.contains("data is expected to result from a call to 'registry.get_record_bytes', was from 'op.identity'"));
assert!(func_error.contains("data is expected to result from a call to 'registry.get_record_bytes', was from 'registry.get_key_bytes'"));
assert!(srv_error.contains("data is expected to result from a call to 'registry.get_record_bytes' or 'registry.get_record_metadata_bytes', was from 'op.identity'"));
assert!(func_error.contains("data is expected to result from a call to 'registry.get_record_bytes' or 'registry.get_record_metadata_bytes', was from 'registry.get_key_bytes'"));
} else {
panic!("incorrect args: expected three arguments")
}
Expand Down Expand Up @@ -1629,6 +1630,62 @@ fn json_builtins() {
}
}

#[test]
fn insecure_sign_verify() {
let kp = KeyPair::from_secret_key(INSECURE_KEYPAIR_SEED.collect(), KeyFormat::Ed25519).unwrap();
let swarms = make_swarms_with_builtins(
1,
"tests/builtins/services".as_ref(),
Some(kp.clone()),
None,
);

let mut client = ConnectedClient::connect_to(swarms[0].multiaddr.clone())
.wrap_err("connect client")
.unwrap();

client.send_particle(
r#"
(seq
(seq
(call relay ("registry" "get_record_bytes") ["key_id" "" [] [] 1 []] data)
(seq
(call relay ("insecure_sig" "sign") [data] sig_result)
(call relay ("insecure_sig" "verify") [sig_result.$.signature.[0]! data] result)
)
)
(call %init_peer_id% ("op" "return") [data sig_result result])
)
"#,
hashmap! {
"relay" => json!(client.node.to_string()),
},
);

use serde_json::Value::Array;
use serde_json::Value::Bool;
use serde_json::Value::Object;

if let [Array(data), Object(sig_result), Bool(result)] =
client.receive_args().unwrap().as_slice()
{
let data: Vec<_> = data.iter().map(|n| n.as_u64().unwrap() as u8).collect();

assert!(sig_result["success"].as_bool().unwrap());
let signature = sig_result["signature"].as_array().unwrap()[0]
.as_array()
.unwrap()
.iter()
.map(|n| n.as_u64().unwrap() as u8)
.collect();
let signature = Signature::from_bytes(kp.public().get_key_format(), signature);
assert!(result);
assert!(kp.public().verify(&data, &signature).is_ok());
} else {
panic!("incorrect args: expected three arguments")
}
}

fn binary(
service: &str,
func: &str,
Expand Down
49 changes: 48 additions & 1 deletion crates/particle-node-tests/tests/spells.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use maplit::hashmap;
use serde_json::{json, Value as JValue};

use connected_client::ConnectedClient;
use created_swarm::make_swarms;
use created_swarm::{make_swarms, make_swarms_with_builtins};
use fluence_spell_dtos::trigger_config::TriggerConfig;
use log_utils::enable_logs;
use service_modules::load_module;
Expand Down Expand Up @@ -1245,3 +1245,50 @@ fn resolve_global_alias() {
assert_eq!(*resolved, tetraplets_service.id);
}
}

#[test]
fn worker_sig_test() {
let swarms = make_swarms_with_builtins(1, "tests/builtins/services".as_ref(), None, None);

let mut client = ConnectedClient::connect_to(swarms[0].multiaddr.clone())
.wrap_err("connect client")
.unwrap();

let script = format!(
r#"
(seq
(seq
(seq
(call %init_peer_id% ("registry" "get_record_bytes") ["key_id" "" [] [] 1 []] data)
(call %init_peer_id% ("sig" "get_peer_id") [] peer_id)
)
(seq
(call %init_peer_id% ("sig" "sign") [data] sig_result)
(call %init_peer_id% ("sig" "verify") [sig_result.$.signature.[0]! data] result)
)
)
(call "{0}" ("op" "return") [sig_result result peer_id])
)
"#,
client.peer_id
);

let mut config = TriggerConfig::default();
config.clock.period_sec = 2;
config.clock.start_sec = 1;
let (_, worker_id) = create_spell(&mut client, &script, config, json!({}));

use serde_json::Value::Bool;
use serde_json::Value::Object;
use serde_json::Value::String;

if let [Object(sig_result), Bool(result), String(peer_id)] =
client.receive_args().unwrap().as_slice()
{
assert!(sig_result["success"].as_bool().unwrap());
assert!(result);
assert_eq!(*peer_id, worker_id);
} else {
panic!("incorrect args: expected two arguments")
}
}
1 change: 1 addition & 0 deletions particle-builtins/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ now-millis = { workspace = true }
toml-utils = { workspace = true }
peer-metrics = { workspace = true }
uuid-utils = { workspace = true }
key-manager = { workspace = true }

libp2p = { workspace = true }
avm-server = { workspace = true }
Expand Down
Loading