From 0580a61612bf7a9b68aa349099a12832869a776a Mon Sep 17 00:00:00 2001 From: Tsachi Herman <24438559+tsachiherman@users.noreply.github.com> Date: Fri, 2 Feb 2024 17:23:35 -0500 Subject: [PATCH] validity & testing (#54) Co-authored-by: Andrew Plaza --- xps-gateway/src/rpc/methods.rs | 15 ++- xps-gateway/tests/integration_test.rs | 166 ++++++++++++++++++++++++-- 2 files changed, 168 insertions(+), 13 deletions(-) diff --git a/xps-gateway/src/rpc/methods.rs b/xps-gateway/src/rpc/methods.rs index 262eb46..0a05697 100644 --- a/xps-gateway/src/rpc/methods.rs +++ b/xps-gateway/src/rpc/methods.rs @@ -18,6 +18,10 @@ use thiserror::Error; use gateway_types::Message; use registry::{error::ContactOperationError, ContactOperations}; +// DEFAULT_ATTRIBUTE_VALIDITY is the hard-coded value we use for the validity of the attributes we set. +// This value is interpeted as number of seconds starting from the block where the attribute is being set. +pub const DEFAULT_ATTRIBUTE_VALIDITY: u64 = 60 * 60 * 24 * 365; + /// Gateway Methods for XPS pub struct XpsMethods { contact_operations: ContactOperations>, @@ -56,13 +60,16 @@ impl XpsServer for XpsMethods

{ signature: Signature, ) -> Result { log::debug!("xps_grantInstallation called"); - let block_number = self.signer.get_block_number().await.unwrap(); - let validity_period: U64 = U64::from(60 * 60 * 24 * 365 / 5); // number of round in one year, assuming 5-second round. - let validity = block_number + validity_period; let result = self .contact_operations - .grant_installation(did, name, value, signature, U256::from(validity.as_u64())) + .grant_installation( + did, + name, + value, + signature, + U256::from(DEFAULT_ATTRIBUTE_VALIDITY), + ) .await .map_err(RpcError::from)?; diff --git a/xps-gateway/tests/integration_test.rs b/xps-gateway/tests/integration_test.rs index c144f2f..7bfde76 100644 --- a/xps-gateway/tests/integration_test.rs +++ b/xps-gateway/tests/integration_test.rs @@ -9,9 +9,9 @@ use lib_didethresolver::{ }; use xps_gateway::rpc::XpsClient; -use ethers::middleware::Middleware; -use ethers::types::{Address, U256, U64}; +use ethers::types::{Address, U256}; use gateway_types::Message; +use xps_gateway::rpc::*; use integration_util::*; @@ -52,10 +52,102 @@ async fn test_wallet_address() -> Result<(), Error> { .await } +#[tokio::test] +async fn test_grant_revoke() -> Result<(), Error> { + with_xps_client(None, |client, context, resolver, anvil| async move { + for (key_index, key) in anvil.keys().iter().enumerate() { + let wallet: LocalWallet = key.clone().into(); + let me = get_user(&anvil, key_index).await; + let name = *b"xmtp/installation/hex "; + let value = b"02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71"; + + let attribute = XmtpAttribute { + purpose: XmtpKeyPurpose::Installation, + encoding: KeyEncoding::Hex, + }; + let signature = wallet + .sign_attribute( + &context.registry, + name, + value.to_vec(), + U256::from(DEFAULT_ATTRIBUTE_VALIDITY), + ) + .await?; + + client + .grant_installation( + format!("0x{}", hex::encode(me.address())), + attribute.clone(), + value.to_vec(), + signature, + ) + .await?; + + let doc = resolver + .resolve_did(me.address(), None) + .await + .unwrap() + .document; + + assert_eq!(doc.verification_method.len(), 2); + assert_eq!( + doc.verification_method[0].id, + DidUrl::parse(format!( + "did:ethr:0x{}#controller", + hex::encode(me.address()) + )) + .unwrap() + ); + assert_eq!( + doc.verification_method[1].id, + DidUrl::parse(format!( + "did:ethr:0x{}?meta=installation#xmtp-0", + hex::encode(me.address()) + )) + .unwrap() + ); + + let signature = wallet + .sign_revoke_attribute(&context.registry, name, value.to_vec()) + .await?; + + client + .revoke_installation( + format!("0x{}", hex::encode(me.address())), + attribute, + value.to_vec(), + signature, + ) + .await?; + + let doc = resolver + .resolve_did(me.address(), None) + .await + .unwrap() + .document; + + log::debug!("{}", serde_json::to_string_pretty(&doc).unwrap()); + + assert_eq!( + doc.verification_method[0].id, + DidUrl::parse(format!( + "did:ethr:0x{}#controller", + hex::encode(me.address()) + )) + .unwrap() + ); + assert_eq!(doc.verification_method.len(), 1); + } + Ok(()) + }) + .await +} + #[tokio::test] async fn test_grant_installation() -> Result<(), Error> { with_xps_client(None, |client, context, resolver, anvil| async move { - let wallet: LocalWallet = anvil.keys()[3].clone().into(); + let keys = anvil.keys(); + let wallet: LocalWallet = keys[3].clone().into(); let me = get_user(&anvil, 3).await; let name = *b"xmtp/installation/hex "; let value = b"02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71"; @@ -65,23 +157,19 @@ async fn test_grant_installation() -> Result<(), Error> { encoding: KeyEncoding::Hex, }; - let block_number = context.signer.get_block_number().await.unwrap(); - let validity_period: U64 = U64::from(60 * 60 * 24 * 365 / 5); // number of round in one year, assuming 5-second round. - let validity = block_number + validity_period; - let signature = wallet .sign_attribute( &context.registry, name, value.to_vec(), - U256::from(validity.as_u64()), + U256::from(DEFAULT_ATTRIBUTE_VALIDITY), ) .await?; client .grant_installation( format!("0x{}", hex::encode(me.address())), - attribute, + attribute.clone(), value.to_vec(), signature, ) @@ -110,6 +198,66 @@ async fn test_grant_installation() -> Result<(), Error> { )) .unwrap() ); + + // now, try to grant again, and ensure it fails as expected: + // (due to bad signature) + match client + .grant_installation( + format!("0x{}", hex::encode(me.address())), + attribute.clone(), + value.to_vec(), + signature, + ) + .await + { + Err(jsonrpsee::core::client::error::Error::Call(e)) => assert_eq!(e.code(), -31999), + _ => panic!("grant_installation call was expected to fail on the second invocation"), + }; + + // calculate the signature again. + let signature = wallet + .sign_attribute( + &context.registry, + name, + value.to_vec(), + U256::from(DEFAULT_ATTRIBUTE_VALIDITY), + ) + .await?; + + // and invoke again. + client + .grant_installation( + format!("0x{}", hex::encode(me.address())), + attribute.clone(), + value.to_vec(), + signature, + ) + .await?; + + let doc = resolver + .resolve_did(me.address(), None) + .await + .unwrap() + .document; + + assert_eq!(doc.verification_method.len(), 2); + assert_eq!( + doc.verification_method[0].id, + DidUrl::parse(format!( + "did:ethr:0x{}#controller", + hex::encode(me.address()) + )) + .unwrap() + ); + assert_eq!( + doc.verification_method[1].id, + DidUrl::parse(format!( + "did:ethr:0x{}?meta=installation#xmtp-1", + hex::encode(me.address()) + )) + .unwrap() + ); + Ok(()) }) .await