Skip to content

Commit

Permalink
feat(template_lib)!: new access rules macro (#1176)
Browse files Browse the repository at this point in the history
Description
---
* Created a new rule! macro in `tari_template_lib` to build `AccessRule`
enums
* Updated all usages of access rules construction to use the new macro,
including builtin templates (e.g. `account` and `account_nft`)

Motivation and Context
---
We want a better way of constructing `AccessRules`. For example, to
restrict a resource to be minted only by a specific component, we need
something like:
```
ResourceBuilder::fungible()
                .mintable(AccessRule::Restricted(RestrictedAccessRule::Require(
                    RequireRule::Require(address.into()),
                )))
```

Instead, we want a new macro that allows us to build access rules in
simpler and more readable way:
```
ResourceBuilder::fungible()
                .mintable(rule!(component(address)))
```

This PR adds a new macro rule! for this purpose. All variants of rules
can be build as follows:
* `rule!(allow_all)`
* `rule!(deny_all)`
* `rule!(component(address))`
* `rule!(resource(address))`
* `rule!(template(address))`
* `rule!(non_fungible(address))`
* `rule!(any_of(component(c_address)), template(t_address)))`

How Has This Been Tested?
---
* New unit test that covers all possible outputs of the new macro
* Existing templates (e.g. account) now use the new macro and all the
related tests still pass

What process can a PR reviewer use to test or verify this change?
---
See previous section

Breaking Changes
---

- [ ] None
- [ ] Requires data directory to be deleted
- [x] Other - As the `tari_template_lib` crate changes, all the builtin
templates (e.g. account) also change.
  • Loading branch information
mrnaveira authored Oct 21, 2024
1 parent 39c638b commit 50e7b8c
Show file tree
Hide file tree
Showing 19 changed files with 230 additions and 96 deletions.
4 changes: 2 additions & 2 deletions dan_layer/consensus/src/hotstuff/on_receive_local_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ impl<TConsensusSpec: ConsensusSpec> OnReceiveLocalProposalHandler<TConsensusSpec
block_description: candidate_block.to_string(),
justify_block: candidate_block.justify().as_leaf_block(),
}
.into());
.into());
};

if justify_block.height() != candidate_block.justify().block_height() {
Expand Down Expand Up @@ -662,7 +662,7 @@ impl<TConsensusSpec: ConsensusSpec> OnReceiveLocalProposalHandler<TConsensusSpec
justify_block_height: justify_block.height(),
candidate_block_height: candidate_block.height(),
}
.into());
.into());
};

if candidate_block.parent() != last_dummy.id() {
Expand Down
19 changes: 7 additions & 12 deletions dan_layer/engine/tests/access_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use tari_template_lib::{
ResourceAccessRules,
ResourceAuthAction,
RestrictedAccessRule,
RuleRequirement,
},
models::{Amount, ComponentAddress, Metadata, NonFungibleId, ResourceAddress, VaultId},
};
Expand All @@ -28,6 +29,8 @@ use tari_template_test_tooling::{
use tari_transaction::Transaction;

mod component_access_rules {
use tari_template_lib::rule;

use super::*;

#[test]
Expand Down Expand Up @@ -147,12 +150,7 @@ mod component_access_rules {
Transaction::builder()
.call_method(component_address, "set_component_access_rules", args![
ComponentAccessRules::new()
.add_method_rule(
"set_value",
AccessRule::Restricted(RestrictedAccessRule::Require(RequireRule::Require(
user_proof.clone().into()
)))
)
.add_method_rule("set_value", rule!(non_fungible(user_proof.clone())))
.default(AccessRule::DenyAll)
])
.sign(&owner_key)
Expand Down Expand Up @@ -228,6 +226,7 @@ mod component_access_rules {

mod resource_access_rules {
use tari_dan_engine::runtime::LockError;
use tari_template_lib::rule;

use super::*;

Expand Down Expand Up @@ -290,9 +289,7 @@ mod resource_access_rules {
test.execute_expect_success(
Transaction::builder()
.call_method(component_address, "set_tokens_access_rules", args![
ResourceAccessRules::new().withdrawable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(user_proof.clone().into())
)))
ResourceAccessRules::new().withdrawable(rule!(non_fungible(user_proof.clone())))
])
.sign(&owner_key)
.build(),
Expand Down Expand Up @@ -330,9 +327,7 @@ mod resource_access_rules {
// Component
ComponentAccessRules::new().default(AccessRule::AllowAll),
// Resource
ResourceAccessRules::new().withdrawable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(user_proof.clone().into())
))),
ResourceAccessRules::new().withdrawable(rule!(non_fungible(user_proof.clone()))),
// Badge recall rule
AccessRule::DenyAll
])
Expand Down
13 changes: 7 additions & 6 deletions dan_layer/engine/tests/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use tari_template_lib::{
constants::XTR,
models::{Amount, ComponentAddress, ResourceAddress},
prelude::AccessRules,
rule,
};
use tari_template_test_tooling::{
support::assert_error::{assert_access_denied_for_action, assert_reject_reason},
Expand Down Expand Up @@ -264,13 +265,13 @@ fn custom_access_rules() {
let (owner_proof, public_key, secret_key) = template_test.create_owner_proof();

let access_rules = AccessRules::new()
.add_method_rule("balance", AccessRule::AllowAll)
.add_method_rule("get_balances", AccessRule::AllowAll)
.add_method_rule("deposit", AccessRule::AllowAll)
.add_method_rule("deposit_all", AccessRule::AllowAll)
.add_method_rule("get_non_fungible_ids", AccessRule::AllowAll)
.add_method_rule("balance", rule!(allow_all))
.add_method_rule("get_balances", rule!(allow_all))
.add_method_rule("deposit", rule!(allow_all))
.add_method_rule("deposit_all", rule!(allow_all))
.add_method_rule("get_non_fungible_ids", rule!(allow_all))
// We are going to make it so anyone can withdraw
.default(AccessRule::AllowAll);
.default(rule!(allow_all));

let result = template_test.execute_expect_success(
Transaction::builder()
Expand Down
70 changes: 24 additions & 46 deletions dan_layer/engine/tests/templates/access_rules/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ mod access_rules_template {
}

pub fn default_rules() -> Component<AccessRulesTest> {
let badges = create_badge_resource(AccessRule::DenyAll);
let badges = create_badge_resource(rule!(deny_all));

let tokens = ResourceBuilder::fungible().initial_supply(1000);

Expand All @@ -70,7 +70,7 @@ mod access_rules_template {
}

pub fn with_auth_hook(allowed: bool, hook: String) -> Component<AccessRulesTest> {
let badges = create_badge_resource(AccessRule::DenyAll);
let badges = create_badge_resource(rule!(deny_all));

let address_alloc = CallerContext::allocate_component_address(None);

Expand All @@ -86,12 +86,12 @@ mod access_rules_template {
attack_component: None,
})
.with_address_allocation(address_alloc)
.with_access_rules(ComponentAccessRules::new().default(AccessRule::AllowAll))
.with_access_rules(ComponentAccessRules::new().default(rule!(allow_all)))
.create()
}

pub fn with_auth_hook_attack_component(component_address: ComponentAddress) -> Component<AccessRulesTest> {
let badges = create_badge_resource(AccessRule::DenyAll);
let badges = create_badge_resource(rule!(deny_all));

let address_alloc = CallerContext::allocate_component_address(None);

Expand All @@ -110,35 +110,23 @@ mod access_rules_template {
attack_component: Some(component_address),
})
.with_address_allocation(address_alloc)
.with_access_rules(ComponentAccessRules::new().default(AccessRule::AllowAll))
.with_access_rules(ComponentAccessRules::new().default(rule!(allow_all)))
.create()
}

pub fn using_badge_rules() -> Component<AccessRulesTest> {
let badges = create_badge_resource(AccessRule::AllowAll);
let badges = create_badge_resource(rule!(allow_all));

let badge_resource = badges.resource_address();
let tokens = ResourceBuilder::fungible()
.mintable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(
NonFungibleAddress::new(badge_resource, NonFungibleId::from_string("mint")).into(),
),
)))
.burnable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(
NonFungibleAddress::new(badge_resource, NonFungibleId::from_string("burn")).into(),
),
)))
.withdrawable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(
NonFungibleAddress::new(badge_resource, NonFungibleId::from_string("withdraw")).into(),
),
)))
.depositable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(
NonFungibleAddress::new(badge_resource, NonFungibleId::from_string("deposit")).into(),
),
)))
.mintable(rule!(non_fungible(
NonFungibleAddress::new(badge_resource, NonFungibleId::from_string("mint")))))
.burnable(rule!(non_fungible(
NonFungibleAddress::new(badge_resource, NonFungibleId::from_string("burn")))))
.withdrawable(rule!(non_fungible(
NonFungibleAddress::new(badge_resource, NonFungibleId::from_string("withdraw")))))
.depositable(rule!(non_fungible(
NonFungibleAddress::new(badge_resource, NonFungibleId::from_string("deposit")))))
.initial_supply(1000);

Component::new(Self {
Expand All @@ -148,27 +136,19 @@ mod access_rules_template {
allowed: true,
attack_component: None,
})
.with_access_rules(ComponentAccessRules::new().default(AccessRule::AllowAll))
.with_access_rules(ComponentAccessRules::new().default(rule!(allow_all)))
.create()
}

pub fn using_resource_rules() -> Component<AccessRulesTest> {
let badges = create_badge_resource(AccessRule::AllowAll);
let badges = create_badge_resource(rule!(allow_all));

let badge_resource = badges.resource_address();
let tokens = ResourceBuilder::fungible()
.mintable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(badge_resource.into()),
)))
.burnable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(badge_resource.into()),
)))
.withdrawable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(badge_resource.into()),
)))
.depositable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(badge_resource.into()),
)))
.mintable(rule!(resource(badge_resource)))
.burnable(rule!(resource(badge_resource)))
.withdrawable(rule!(resource(badge_resource)))
.depositable(rule!(resource(badge_resource)))
.initial_supply(1000);

Component::new(Self {
Expand All @@ -178,18 +158,16 @@ mod access_rules_template {
allowed: true,
attack_component: None,
})
.with_access_rules(ComponentAccessRules::new().default(AccessRule::AllowAll))
.with_access_rules(ComponentAccessRules::new().default(rule!(allow_all)))
.create()
}

pub fn resource_actions_restricted_to_component() -> Component<AccessRulesTest> {
let badges = create_badge_resource(AccessRule::AllowAll);
let badges = create_badge_resource(rule!(allow_all));

let allocation = CallerContext::allocate_component_address(None);
let tokens = ResourceBuilder::fungible()
.mintable(AccessRule::Restricted(RestrictedAccessRule::Require(
RequireRule::Require(allocation.address().clone().into()),
)))
.mintable(rule!(component(*allocation.address())))
// Only access rules apply, this just makes the test simpler because we do not need to change the transaction signer
.with_owner_rule(OwnerRule::None)
.initial_supply(1000);
Expand All @@ -202,7 +180,7 @@ mod access_rules_template {
attack_component: None,
})
.with_address_allocation(allocation)
.with_access_rules(ComponentAccessRules::new().default(AccessRule::AllowAll))
.with_access_rules(ComponentAccessRules::new().default(rule!(allow_all)))
.create()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ mod faucet_template {
impl ConfidentialFaucet {
pub fn mint(confidential_proof: ConfidentialOutputStatement) -> Component<Self> {
let coins = ResourceBuilder::confidential()
.mintable(AccessRule::AllowAll)
.mintable(rule!(allow_all))
.initial_supply(confidential_proof);

Component::new(Self {
Expand All @@ -48,7 +48,7 @@ mod faucet_template {
view_key: RistrettoPublicKeyBytes,
) -> Component<Self> {
let coins = ResourceBuilder::confidential()
.mintable(AccessRule::AllowAll)
.mintable(rule!(allow_all))
.with_view_key(view_key)
.initial_supply(confidential_proof);

Expand Down
4 changes: 2 additions & 2 deletions dan_layer/engine/tests/templates/nft/basic_nft/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ mod sparkle_nft_template {
];
let bucket = ResourceBuilder::non_fungible().with_token_symbol("SPKL")
// Allow minting and burning for tests
.mintable(AccessRule::AllowAll)
.burnable(AccessRule::AllowAll)
.mintable(rule!(allow_all))
.burnable(rule!(allow_all))
.initial_supply(tokens);

Component::new(Self {
Expand Down
2 changes: 1 addition & 1 deletion dan_layer/engine/tests/templates/nft/emoji_id/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ mod emoji_id {
// Create the non-fungible resource with empty initial supply
let resource_address = ResourceBuilder::non_fungible()
.with_token_symbol("emo")
.mintable(AccessRule::AllowAll)
.mintable(rule!(allow_all))
.build();
let earnings = Vault::new_empty(payment_resource_address);
Component::new(Self {
Expand Down
2 changes: 1 addition & 1 deletion dan_layer/engine/tests/templates/nft/nft_list/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ mod sparkle_nft_template {
pub fn new() -> Component<Self> {
let resource_address = ResourceBuilder::non_fungible()
.with_token_symbol("sparkle")
.mintable(AccessRule::AllowAll)
.mintable(rule!(allow_all))
.build();

Component::new(Self { resource_address })
Expand Down
2 changes: 1 addition & 1 deletion dan_layer/engine/tests/templates/nft/tickets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ mod tickets {
let resource_address = ResourceBuilder::non_fungible().with_token_symbol("tix")
// The event description is common for all tickets
.add_metadata("event", event_description)
.mintable(AccessRule::Restricted(RestrictedAccessRule::Require(RequireRule::Require(owner.into()))))
.mintable(rule!(non_fungible(owner)))
.build();

// Mint the initial tickets
Expand Down
6 changes: 3 additions & 3 deletions dan_layer/engine/tests/templates/recall/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ mod template {
confidential_supply: ConfidentialOutputStatement,
) -> (Component<Self>, ResourceAddress, ResourceAddress, ResourceAddress) {
let fungible = ResourceBuilder::fungible()
.recallable(AccessRule::AllowAll)
.recallable(rule!(allow_all))
.initial_supply(Amount(1_000_000));

let fungible_resource = fungible.resource_address();

let non_fungible = ResourceBuilder::non_fungible()
.recallable(AccessRule::AllowAll)
.recallable(rule!(allow_all))
.initial_supply((1..=10).map(NonFungibleId::from_u32));
let non_fungible_resource = non_fungible.resource_address();

let confidential = ResourceBuilder::confidential()
.recallable(AccessRule::AllowAll)
.recallable(rule!(allow_all))
.initial_supply(confidential_supply);
let confidential_resource = confidential.resource_address();

Expand Down
2 changes: 1 addition & 1 deletion dan_layer/engine/tests/templates/resource/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ mod template {
let non_fungible = ResourceBuilder::non_fungible()
.initial_supply([NonFungibleId::from_u64(1), NonFungibleId::from_u64(2)]);
let confidential = ResourceBuilder::confidential()
.mintable(AccessRule::AllowAll)
.mintable(rule!(allow_all))
.initial_supply(ConfidentialOutputStatement::mint_revealed(1000));

Component::new(Self {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod template {

impl Shenanigans {
pub fn new() -> Component<Shenanigans> {
let resource = ResourceBuilder::non_fungible().mintable(AccessRule::AllowAll).build();
let resource = ResourceBuilder::non_fungible().mintable(rule!(allow_all)).build();

Component::new(Self {
vault: Vault::new_empty(resource),
Expand Down
2 changes: 1 addition & 1 deletion dan_layer/engine/tests/templates/shenanigans/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mod template {
..Default::default()
})
.with_access_rules(AccessRules::allow_all())
.with_owner_rule(OwnerRule::ByAccessRule(AccessRule::AllowAll))
.with_owner_rule(OwnerRule::ByAccessRule(rule!(allow_all)))
.create()
}

Expand Down
8 changes: 4 additions & 4 deletions dan_layer/engine/tests/templates/state/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ mod state_template {
impl State {
pub fn new() -> Component<Self> {
Component::new(Self { value: 0 })
.with_access_rules(AccessRules::new().default(AccessRule::AllowAll))
.with_access_rules(AccessRules::new().default(rule!(allow_all)))
.create()
}

pub fn create_multiple(n: u32) {
(0..n).for_each(|i| {
Component::new(Self { value: i })
.with_access_rules(AccessRules::new().default(AccessRule::AllowAll))
.with_access_rules(AccessRules::new().default(rule!(allow_all)))
.create();
});
}
Expand All @@ -49,8 +49,8 @@ mod state_template {
Component::new(Self { value: 0 })
.with_access_rules(
AccessRules::new()
.add_method_rule("get", AccessRule::AllowAll)
.default(AccessRule::DenyAll),
.add_method_rule("get", rule!(allow_all))
.default(rule!(deny_all)),
)
.create()
}
Expand Down
Loading

0 comments on commit 50e7b8c

Please sign in to comment.