Skip to content

Access Controller manifest classifications#140

Open
GhenadieVP wants to merge 26 commits intodevelopfrom
access_controller_manifest_classifications
Open

Access Controller manifest classifications#140
GhenadieVP wants to merge 26 commits intodevelopfrom
access_controller_manifest_classifications

Conversation

@GhenadieVP
Copy link
Contributor

@GhenadieVP GhenadieVP commented Oct 4, 2025

  • Entity Securify classification
  • AC recovery classification
  • AC Cancel timed recovery classification
  • AC Confirm timed recovery classification

@GhenadieVP GhenadieVP marked this pull request as ready for review October 7, 2025 07:00
@GhenadieVP GhenadieVP changed the title WIP: Access Controller manifest classifications Access Controller manifest classifications Oct 7, 2025
@GhenadieVP GhenadieVP changed the base branch from main to develop November 19, 2025 13:53
GhenadieVP and others added 10 commits November 19, 2025 16:16
* Bump IndexMap version (#142)

* bump

* bump

* disable SCCache to validate the CI

* Bump crossbeam-channel from 0.5.13 to 0.5.15 (#139)

Bumps [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) from 0.5.13 to 0.5.15.
- [Release notes](https://github.com/crossbeam-rs/crossbeam/releases)
- [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md)
- [Commits](crossbeam-rs/crossbeam@crossbeam-channel-0.5.13...crossbeam-channel-0.5.15)

---
updated-dependencies:
- dependency-name: crossbeam-channel
  dependency-version: 0.5.15
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* comment all jobs but one

* comment rest of workflow

* update artifacts jobs to v4

* update

* update artifacts actions

* specifiy download artifact dir

* uncomment all

* fix all artifacts steps to v4
}
}

fn is_instruction_permitted(context: InstructionContext<'_>) -> bool {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we can rely more on the TypedManifestNativeInvocation type we can collapse this entire function into a single matches! statement:

matches!(
    context,
    InstructionContext::InvocationInstruction {
        instruction,
        typed_native_invocation: Some(
            TypedNativeInvocation {
                // Fee payment methods
                invocation: TypedManifestNativeInvocation::AccountBlueprintInvocation(AccountBlueprintInvocation::Method(AccountBlueprintMethod::LockFee(..)))
                | TypedManifestNativeInvocation::AccountBlueprintInvocation(AccountBlueprintInvocation::Method(AccountBlueprintMethod::LockContingentFee(..)))
                | TypedManifestNativeInvocation::AccessControllerBlueprintInvocation(AccessControllerBlueprintInvocation::Method(AccessControllerBlueprintMethod::LockRecoveryFee(..)))
                // Recovery methods
                | TypedManifestNativeInvocation::AccessControllerBlueprintInvocation(AccessControllerBlueprintInvocation::Method(AccessControllerBlueprintMethod::TimedConfirmRecovery(..))),
                ..
            }
        ),
        ..
    }
    // Only call-method invocations are permitted.
    if instruction.belongs_to_invocation_instructions_and(|instruction| instruction.is_call_method_instruction())
);

)
| (
Some(GroupedEntityType::AccessControllerEntities(..)),
ACCESS_CONTROLLER_CREATE_PROOF_IDENT
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this should be allowed when confirming a timed recovery?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto: consider using the syntax I provided in the previous comment for a simpler way to express what instructions are permitted and what isn't.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my understanding this is used for the scenario when the fee payer is a securified account, for which case it is needed to create the proof for locking the fee from the account

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, then we should keep it. Consider using the syntax that I mentioned.

) => true,
// Recovery idents - starting and confirming
(
Some(GroupedEntityType::AccessControllerEntities(..)),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's some inconsistency between this method and the process_instruction method.

In the process_instruction method you process the instructions which initiate recovery, but not the instructions that confirm, timed confirm, or cancel the recovery proposal. So there's a disconnect between the instructions permitted in this analyzer and the instructions processed by this analyzer which is mostly incorrect.

Some(GroupedEntityType::AccessControllerEntities(..)),
ACCESS_CONTROLLER_INITIATE_RECOVERY_AS_PRIMARY_IDENT
| ACCESS_CONTROLLER_INITIATE_RECOVERY_AS_RECOVERY_IDENT
| ACCESS_CONTROLLER_QUICK_CONFIRM_PRIMARY_ROLE_RECOVERY_PROPOSAL_IDENT
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there no ACCESS_CONTROLLER_TIMED_CONFIRM_RECOVERY_IDENT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll follow the spec doc you have shared, I am not entirely sure if many of these are needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it would be better to do that since it covers all of the methods that should be covered.

invocation:
TypedManifestNativeInvocation::AccessControllerBlueprintInvocation(
AccessControllerBlueprintInvocation::Method(
AccessControllerBlueprintMethod::InitiateRecoveryAsPrimary(..)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you process recovery initiation but doesn't process recovery confirmation but you permit recovery confirmation in this analyzer which is incorrect.

What's the purpose of this analyzer? To catch all ACs for which we started recovery? To catch all ACs for which we touch any recovery operation? To catch all ACs for which we confirm recovery? If we be more specific about it's purpose then we can agree on how to implement it best.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of this analyzer? To catch all ACs for which we started recovery?

Yes. This might analyzer might be a bit specific to Wallet needs, where we do care only to determine the ac for which the recovery is started. Down the line, the Wallet might not even sign this specific manifest, but a different variant based on the user signature flow.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This might analyzer might be a bit specific to Wallet needs, where we do care only to determine the ac for which the recovery is started.

If you only want to determine the ACs for which recovery has started, then do you assume that in some of these manifests users will also complete the recovery? Because this would then determine what set of instructions should be permitted or not permitted.

(
Some(GroupedEntityType::AccessControllerEntities(..)),
ACCESS_CONTROLLER_STOP_TIMED_RECOVERY_IDENT
| ACCESS_CONTROLLER_CANCEL_PRIMARY_ROLE_RECOVERY_PROPOSAL_IDENT
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The analyzer is called StopTimedRecovery but we permit these methods. Why? Also, we permit them but don't process them, why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is allowed to perform the stop and cancel the proposal in the same transaction, instead of having separate transaction for stopping the timed recovery and then for cancelling the proposal.
it is not processed given that we do extract the necessary information from the StopTimedRecovery, but I guess there should be at least a validation that stop and cancel refer to the same AC.

let blueprint_id =
BlueprintId::new(package_address, blueprint_name);
let typed_invocation =
TypedManifestNativeInvocation::from_function_invocation(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The typed invocation is already available in the context. You don't need to re-create it again.

}
}

fn is_instruction_permitted(context: InstructionContext<'_>) -> bool {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the logic in this function can be more succinctly expressed as:

matches!(
    context,
    InstructionContext::InvocationInstruction {
        typed_native_invocation: Some(TypedNativeInvocation {
            invocation:
                TypedManifestNativeInvocation::AccountBlueprintInvocation(
                    AccountBlueprintInvocation::Method(
                        AccountBlueprintMethod::Securify(..)
                        | AccountBlueprintMethod::CreateProofOfAmount(..)
                        | AccountBlueprintMethod::CreateProofOfNonFungibles(..)
                        | AccountBlueprintMethod::LockFee(..)
                        | AccountBlueprintMethod::LockContingentFee(..)
                    )
                )
                | TypedManifestNativeInvocation::IdentityBlueprintInvocation(
                    IdentityBlueprintInvocation::Method(
                        IdentityBlueprintMethod::Securify(..)
                    )
                )
                | TypedManifestNativeInvocation::AccessControllerBlueprintInvocation(
                    AccessControllerBlueprintInvocation::Function(
                        AccessControllerBlueprintFunction::Create(..)
                    )
                    | AccessControllerBlueprintInvocation::Method(
                        AccessControllerBlueprintMethod::CreateProof(..)
                    )
                )
                | TypedManifestNativeInvocation::MetadataBlueprintInvocation(
                    MetadataBlueprintInvocation::Method(
                        MetadataBlueprintMethod::Set(..)
                    )
                ),
            ..
        }),
        ..
    }
    | InstructionContext::NonInvocationInstruction {
        instruction: GroupedInstruction::ProofInstructions(..)
        | GroupedInstruction::TakeFromWorktopInstructions(..)
        | GroupedInstruction::AddressAllocationInstructions(
            AddressAllocationInstructions::AllocateGlobalAddress(
                AllocateGlobalAddress { package_address: ACCESS_CONTROLLER_PACKAGE, .. }
            )
        ),
        ..
    }
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants