-
Notifications
You must be signed in to change notification settings - Fork 1
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
[WIP] Apply Shield Wallet Interaction Part 2 #355
base: main
Are you sure you want to change the base?
[WIP] Apply Shield Wallet Interaction Part 2 #355
Conversation
}; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct AccessControllerFactorsAndTimeInput { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shared type to create:
AccessControllerInitiateRecoveryAsPrimaryInput
AccessControllerInitiateRecoveryAsRecoveryInput
AccessControllerQuickConfirmPrimaryRoleRecoveryProposalInput
AccessControllerQuickConfirmRecoveryRoleRecoveryProposalInput
AccessControllerTimedConfirmRecoveryInput
Input to call_method
instruction, using SecurityStructureOfFactorInstances
- which is Into<RuleSet>
(and time u32).
let entity_address = securified_entity.entity.address(); | ||
|
||
// ACCESS_CONTROLLER_CREATE_PROOF_IDENT | ||
let mut builder = TransactionManifest::produce_owner_badge( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does:
builder.call_method(
access_controller_address.scrypto(),
ACCESS_CONTROLLER_CREATE_PROOF_IDENT,
(),
);
|
||
// INITIATE RECOVERY | ||
let (init_method, init_input) = | ||
kind.input_for_initialization(factors_and_time_input); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depending on selector of which of the six TransactionManifest
flavours as selected by kind: TransactionManifestApplySecurityShieldKind
we use different roles for initialization of recovery (and the correct concrete scrypto "Input"-type (Box dyn-ed))
For details see transaction_manifest_apply_security_shield_kind.rs
which was added by this PR
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #355 +/- ##
==========================================
- Coverage 92.59% 92.40% -0.20%
==========================================
Files 1169 890 -279
Lines 26153 22859 -3294
Branches 81 81
==========================================
- Hits 24217 21122 -3095
+ Misses 1925 1726 -199
Partials 11 11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
...ction/manifests/src/manifests_security_shield/manifests_securify_shield_securified_entity.rs
Outdated
Show resolved
Hide resolved
// Set Rola Key | ||
let should_set_rola_key = security_structure_of_factor_instances | ||
.authentication_signing_factor_instance | ||
!= securified_entity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dont set ROLA key if it is unchanged
owner_badge_bucket_name, | ||
); | ||
}; | ||
let (mut builder, owner_badge_bucket) = Self::put_owner_badge_in_bucket( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still calls "securify" - just refactored a bit.
PrimaryAndExplicitConfirmation, | ||
|
||
/// (Primary Time) ‼️ REQUIRES "Dugong" ‼️ | ||
PrimaryWithTimedAutoConfirm, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@GhenadieVP I think Matt said we would have Dugong
available. So we will remove this comment once Dugong is live. Maybe I should comment out PrimaryWithTimedAutoConfirm
for now...
pub fn input_for_initialization( | ||
&self, | ||
factors_and_time: &AccessControllerFactorsAndTimeInput, | ||
) -> (&'static str, Box<dyn CallMethodInput>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dhedey naivly I tried returning (&'static str, impl ResolvableArguments)
which did not compile. Then I tried Box<dyn ResolvableArguments>
which compiled here, but did not compile when I tried passing it to call_method
directly, so I tried .deref()
on the box to get the "inner" dyn ResolvableArguments
which did not compile... bah. But when I introduced this "dummy trait" (see above):
// Trickery to allow `Box<dyn ResolvableArguments>` - which is not allowed it seems,
// but this solves it, since in Scrypto they impl ResolvableArguments for ManifestEncode + ManifestSborTuple
pub trait CallMethodInput: ManifestEncode + ManifestSborTuple {}
impl<T: ManifestEncode + ManifestSborTuple> CallMethodInput for T {}
then everything works. It is just 2 lines of code so fine for now. But maybe you have ideas on how it can be removed? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it, the reason why that trick works is subtle (basically T: CallMethodInput
=> T: ManifestEncode + ManifestSborTuple
=> Box<T>: ManifestEncode + ManifestSborTuple
(via blanket impls on Box<T>
of ManifestEncode and ManifestSborTuple) => Box<T>: ResolvableArguments
).
The trick seems fine to me.
Other fixes in the repo would be to re-work the ResolvableArguments
trait in the scrypto repo, either:
- To itself have the
: ManifestEncode + ManifestSborTuple
bounds - To be dyn-friendly, e.g. changing the
self
to&self
. CurrentlyBox<dyn ResolvableArguments>
has no methods because theresolve
method isn't dyn-friendly.
pub trait ResolvableArguments {
fn resolve(self) -> ManifestValue;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
(SCRYPTO_ACCESS_CONTROLLER_QUICK_CONFIRM_PRIMARY_ROLE_RECOVERY_PROPOSAL_IDENT, Box::new(ScryptoAccessControllerQuickConfirmPrimaryRoleRecoveryProposalInput::from(factors_and_time))) | ||
} | ||
} else { | ||
// Time based |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://github.com/radixdlt/sargon/pull/355/files#r1928373228 I think this is wrong, should probably update this method to return Option<(&'static str, Box<dyn CallMethodInput>)>
and then None
if we cannot quick confirm.
EntitySecurityState::Securified { value } => { | ||
builder = builder.call_method( | ||
value.access_controller_address.scrypto(), | ||
ACCESS_CONTROLLER_CREATE_PROOF_IDENT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is ACCESS_CONTROLLER_CREATE_PROOF_IDENT
correct for when we are performing recovery?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this question does not make any sense... but I thought we always needed to invoke an instruction which triggers requirement to "auth". but maybe the INITIATE recovery methods will do that...?
let access_controller_address = securified_entity | ||
.securified_entity_control | ||
.access_controller_address; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have forgotten to add the withdrawal of XRD from AccessControllera XRD vault.
I’m adding it now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right we need to add the locking of fee against XRD vault of AccessController later (like the top up) - since we dont know how big a fee to lock. Ive added modify_manifest_add_lock_fee_against_xrd_vault_of_access_controller
. Take a look at it 4d8fc6d
.securified_entity_control | ||
.access_controller_address; | ||
// Lock fee against XRD vault of the access controller | ||
builder = builder.call_method( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@0xOmarA here I'm appending this instruction last. Is that OK? Or must this be prepended, index 0 of the manifest? if so I need to do a lot of trickery to do that. Since I cannot create the instruction in rust code "manually" and since calling buider.call_method
will put it last...
@GhenadieVP alternatively we just lock a "large" amount. Which ""should work"" for most shields... and if we do that we can lock fee in apply_security_shield_for_securified_entity
at index 0 https://github.com/radixdlt/sargon/blob/ac/wallet_interaction_applying_shield_abw-4056_part2/crates/transaction/manifests/src/manifests_security_shield/manifests_securify_shield_securified_entity.rs#L37
/// be quick confirmed. We need to figure out how we best represent this | ||
/// in Profile. Perhaps a new variant on ProvisionalSecurityConfig? Something | ||
/// like: | ||
/// `WaitingForTimedRecovery(SecurityStructureOfFactorInstances)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@GhenadieVP good thing we kept ProvisionalSecurifiedConfig
an enum! I think we need a second variant - WaitingForTimedRecovery(SecurityStructureOfFactorInstances)
…ear that it does not happen automagically.
@@ -247,7 +247,7 @@ mod tests { | |||
} | |||
] | |||
}, | |||
"numberOfDaysUntilAutoConfirm": 14 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking profile change! But ok since only Radix Wallet team devs are affected.
numberOfDaysUntilAutoConfirm
made it sound like confirmation would happen automagically. Which perhaps even I believed they would when I named this variable...
@@ -39,13 +39,14 @@ pub struct AbstractMatrixBuilderOrBuilt< | |||
pub(crate) confirmation_role: | |||
AbstractRoleBuilderOrBuilt<{ ROLE_CONFIRMATION }, MODE_OF_ROLE, FACTOR>, | |||
|
|||
pub number_of_days_until_auto_confirm: u16, | |||
pub number_of_days_until_timed_confirmation_is_callable: u16, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking profile change! But ok since only Radix Wallet team devs are affected.
numberOfDaysUntilAutoConfirm
made it sound like confirmation would happen automagically. Which perhaps even I believed they would when I named this variable...
#[error("The number of days until auto confirm must be greater than zero")] | ||
NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero, | ||
#[error("The number of days until timed confirm is callable must be greater than zero")] | ||
NumberOfDaysUntilTimeBasedConfirmationMustBeGreaterThanZero, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking Profile format change number 2 - @sergiupuhalschi-rdx / @danvleju-rdx / @matiasbzurovski might get affected in host
@@ -379,17 +379,20 @@ impl MatrixBuilder { | |||
self.primary_role.get_threshold() | |||
} | |||
|
|||
pub fn set_number_of_days_until_auto_confirm( | |||
pub fn set_number_of_days_until_timed_confirmation_is_callable( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking API change - @sergiupuhalschi-rdx / @danvleju-rdx / @matiasbzurovski will get affected in host
); | ||
|
||
// QUICK CONFIRM RECOVERY - Only if we can exercise the confirmation role explicitly. | ||
if let Some((confirm_method, confirm_input)) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only call "quick confirm" if we can exercise confirmation role explicitly. Else we skip quick confirm and we will LATER (number_of_days_until_timed_confirmation_is_callable
later) make another transaction.
@@ -25,7 +25,7 @@ macro_rules! matrix_conversion { | |||
pub recovery_role: #recovery_role_type, | |||
pub confirmation_role: #confirmation_role_type, | |||
|
|||
pub number_of_days_until_auto_confirm: u16, | |||
pub number_of_days_until_timed_confirmation_is_callable: u16, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@GhenadieVP we should probably change this to number_of_minutes
though! Which easily support days. But if we ever wanted to allow less than a day in the future we cannot. i.e. the host and builders will continue using Day
as smallest granularity, but Profile probably SHOULD use Minute
as time unit - since that is what rest of Radix Stack uses. Right? If you agree, I will make that change now - so we dont have to have two consequetive breaking profile changes on top of each other.
#[derive(Clone, Debug, PartialEq, Eq, Hash, enum_iterator::Sequence)] | ||
pub enum TransactionManifestApplySecurityShieldKind { | ||
/// (Primary Recovery Confirmation) | ||
PrimaryAndRecoveryWithExplicitConfirmation, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Under the two of three model, lots of these don't make sense to me.
I'd expect something like:
InitiateWithPrimaryCompleteWithRecovery
InitiateWithPrimaryCompleteWithConfirmation
InitiateWithRecoveryCompleteWithConfirmation
InitiateWithPrimaryDelayedCompletion
// Either Timed or (in future) external factorsInitiateWithRecoveryDelayedCompletion
// Either Timed or (in future) external factors
And then in future, there might be modes where the user can't initiate themselves and needs to send a request to an external source (e.g. a friend or custodian) to do, which might look like:
ExternalInitiateWithPrimary
ExternalInitiateWithRecovery
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes good point.
Thanks!
I answered on Slack too
Jira ABW-4056
Caution
Sargon breaking change in Profile format - only Wallet team devs affected since models are MFA models end users have not been able to produce yet.
renamed "auto_confirm" to "time_based_confirmation" instead since "auto" was indeed very misleading! Since we MUST call confirm in a manifest and submit to the network. Is does not happen "automatically"!
Tip
Not ready to be merged but I need early input from protocol team on logic
Note
Part 2 of N
Part 1 merged into main
Update Factors of Securified Entities
For securified entities we need six different manifests to sign depending on which roles the user is able to exercise at the moment of applying the shield.
Host will display the variant which is exercising all roles with confirmation rule using quick confirm - but if user slides to sign, Sargon will under the hood try to sign all six (maybe less if we can finish early). If she does not have access to some factor belonging to Primary role she can skip signing with that factor and all manifest variants out of those six which requires Primary will be invalid. We can still withdraw XRD from AccessController XRD vault so we can continue trying sign manifests requiring Recovery role. Just that we cannot top up the XRD vault of the access controller. If she manages to sign with the required factors of Recovery role we proceed trying to sign with factors of ConfirmationRole. Which can fail too, then we use time based fallback, if user was unable to exercise Primary Role and Reocery role we fail.
This PR adds logic for creating all six flavours: