Skip to content

Commit

Permalink
e2e test for controller execution
Browse files Browse the repository at this point in the history
  • Loading branch information
UMR1352 committed Nov 27, 2024
1 parent 3171d71 commit c44ef6d
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ module iota_identity::identity {

/// Destroys a `ControllerCap`. Can only be used after a controller has been removed from
/// the controller committee.
public fun destroy_controller_cap(self: &Identity, cap: ControllerCap) {
public(package) fun destroy_controller_cap(self: &Identity, cap: ControllerCap) {
self.did_doc.destroy_controller_cap(cap);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ module iota_identity::multicontroller {
/// Destroys a `ControllerCap`. Can only be used after a controller has been removed from
/// the controller committee.
public fun destroy_controller_cap<V>(self: &Multicontroller<V>, cap: ControllerCap) {
assert!(self.controllers.contains(&cap.id().to_inner()), EInvalidController);
assert!(!self.controllers.contains(&cap.id().to_inner()), EInvalidController);

cap.delete();
}
Expand Down
4 changes: 2 additions & 2 deletions identity_iota_core/src/rebased/client/read_only.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ impl IdentityClientReadOnly {
.map_err(|e| Error::ObjectLookup(e.to_string()))
}

#[allow(dead_code)]
pub(crate) async fn get_object_ref_by_id(&self, obj: ObjectID) -> Result<Option<OwnedObjectRef>, Error> {
/// Returns an object's [`OwnedObjectRef`], if any.
pub async fn get_object_ref_by_id(&self, obj: ObjectID) -> Result<Option<OwnedObjectRef>, Error> {
self
.read_api()
.get_object_with_options(obj, IotaObjectDataOptions::default().with_owner())
Expand Down
12 changes: 9 additions & 3 deletions identity_iota_core/src/rebased/migration/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::HashSet;
use std::ops::Deref;
use std::str::FromStr;

use crate::rebased::proposals::ControllerExecution;
use crate::rebased::sui::types::Number;
use crate::IotaDID;
use crate::IotaDocument;
Expand Down Expand Up @@ -175,13 +176,18 @@ impl OnChainIdentity {
}

/// Borrows assets owned by this [`OnChainIdentity`] to use them in a custom transaction.
/// # Notes
/// Make sure to call [`super::Proposal::with_intent`] before executing the proposal.
/// Failing to do so will make [`crate::proposals::ProposalT::execute`] return an error.
pub fn borrow_assets(&mut self) -> ProposalBuilder<'_, BorrowAction> {
ProposalBuilder::new(self, BorrowAction::default())
}

/// Borrows a `ControllerCap` with ID `controller_cap` owned by this identity in a transaction.
/// This proposal is used to perform operation on a sub-identity controlled
/// by this one.
pub fn controller_execution(&mut self, controller_cap: ObjectID) -> ProposalBuilder<'_, ControllerExecution> {
let action = ControllerExecution::new(controller_cap, self);
ProposalBuilder::new(self, action)
}

/// Returns historical data for this [`OnChainIdentity`].
pub async fn get_history(
&self,
Expand Down
82 changes: 82 additions & 0 deletions identity_iota_core/tests/e2e/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ use identity_iota_core::IotaDocument;
use identity_verification::MethodScope;
use identity_verification::VerificationMethod;
use iota_sdk::rpc_types::IotaObjectData;
use iota_sdk::types::base_types::ObjectID;
use iota_sdk::types::base_types::SequenceNumber;
use iota_sdk::types::object::Owner;
use iota_sdk::types::transaction::ObjectArg;
use iota_sdk::types::TypeTag;
use iota_sdk::types::IOTA_FRAMEWORK_PACKAGE_ID;
use move_core_types::ident_str;
Expand Down Expand Up @@ -355,3 +358,82 @@ async fn borrow_proposal_works() -> anyhow::Result<()> {

Ok(())
}

#[tokio::test]
async fn controller_execution_works() -> anyhow::Result<()> {
let test_client = get_test_client().await?;
let identity_client = test_client.new_user_client().await?;

let mut identity = identity_client
.create_identity(TEST_DOC)
.finish()
.execute(&identity_client)
.await?
.output;
let identity_address = identity.id().into();

// Create a second identity owned by the first.
let identity2 = identity_client
.create_identity(TEST_DOC)
.controller(identity_address, 1)
.threshold(1)
.finish()
.execute(&identity_client)
.await?
.output;

// Let's find identity's controller cap for identity2.
let controller_cap = identity_client
.find_owned_ref_for_address(
identity_address,
format!("{}::controller::ControllerCap", identity_client.package_id()).parse()?,
|_| true,
)
.await?
.expect("identity is a controller of identity2");

// Perform an action on `identity2` as a controller of `identity`.
let ProposalResult::Pending(controller_execution) = identity
.controller_execution(controller_cap.0)
.finish(&identity_client)
.await?
.execute(&identity_client)
.await?
.output
else {
panic!("controller execution proposals cannot be executed without being driven by the user")
};
let identity2_ref = identity_client.get_object_ref_by_id(identity2.id()).await?.unwrap();
let Owner::Shared { initial_shared_version } = identity2_ref.owner else {
panic!("identity2 is shared")
};
let tx_output = controller_execution
.into_tx(&mut identity, &identity_client)
.await?
// specify the operation to perform with the borrowed identity's controller_cap
.with_intent(|ptb, controller_cap| {
let identity2 = ptb
.obj(ObjectArg::SharedObject {
id: identity2_ref.object_id(),
initial_shared_version,
mutable: true,
})
.unwrap();

let token_to_revoke = ptb.pure(ObjectID::ZERO).unwrap();

ptb.programmable_move_call(
identity_client.package_id(),
ident_str!("identity").into(),
ident_str!("revoke_token").into(),
vec![],
vec![identity2, *controller_cap, token_to_revoke],
);
})
.execute(&identity_client)
.await?;

assert!(tx_output.response.status_ok().unwrap());

Ok(())
}

0 comments on commit c44ef6d

Please sign in to comment.