Skip to content
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

feat: Add in place update support to versioned macro #1755

Merged
merged 21 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
70b4298
feat: Add in place update support to versioned macro
dhedey Mar 30, 2024
62fc8ae
fix: Build error and warning fixes
dhedey Mar 30, 2024
bcfc9dc
tweak: Payload types implement HasUniqueLatestVersion
dhedey Mar 31, 2024
7641bd6
Merge branch 'develop' into tweak/versioned-macro-improvements
dhedey Apr 11, 2024
c2720e5
feat: Add #[sbor(as_type)] and update versioned
dhedey Apr 20, 2024
b2b3af1
tweak: Small tweaks to `evaluate_eager_macros`
dhedey Apr 20, 2024
69e5cfb
Merge branch 'develop' into tweak/versioned-macro-improvements
dhedey Apr 20, 2024
4e8d53b
fix: Fix sbor as_type encode which wasn't saved
dhedey Apr 21, 2024
e8e1b7f
tweak: Implement SBOR for Nibble using transparent
dhedey Apr 21, 2024
d83f581
fix: Fix comments
dhedey Apr 22, 2024
cf03392
fix: Fix versioned discriminators to be 0-indexed
dhedey Apr 22, 2024
c351677
feature: Add support for StaticMultiVersioned
dhedey Apr 22, 2024
f364d7c
fix: Fix scrypto-test compilation
dhedey Apr 22, 2024
b790c58
Merge branch 'develop' into tweak/versioned-macro-improvements
dhedey Apr 22, 2024
de54681
fix: Fixed package_invalid tests
dhedey Apr 22, 2024
ce662a2
feat: Fixed eager macro, used it for define_versioned!
dhedey Apr 23, 2024
9e20772
fix: Fix scrypto_env tests
dhedey Apr 23, 2024
36053ba
fix: Fix formatting
dhedey Apr 23, 2024
de487ac
fix: Fix radix-sbor-derive tests
dhedey Apr 23, 2024
75bcfa6
markups: Tweaks to versioned method naming and eager_replace calls
dhedey Apr 23, 2024
a675f6d
fix: Fixes eager_replace test which was compiler-version dependent
dhedey Apr 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/blueprints/radiswap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ mod radiswap {
let input_amount = input_bucket.amount();

let input_reserves = reserves
.remove(&input_bucket.resource_address())
.swap_remove(&input_bucket.resource_address())
iamyulong marked this conversation as resolved.
Show resolved Hide resolved
.expect("Resource does not belong to the pool");
let (output_resource_address, output_reserves) = reserves.into_iter().next().unwrap();

Expand Down
9 changes: 4 additions & 5 deletions assets/blueprints/radiswap/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,10 @@ fn reading_and_asserting_against_radiswap_pool_state() -> Result<(), RuntimeErro
})?;
let (amount1, amount2) = env.with_component_state::<VersionedTwoResourcePoolState, _, _, _>(
pool_component,
|VersionedTwoResourcePoolState::V1(TwoResourcePoolStateV1 {
vaults: [(_, vault1), (_, vault2)],
..
}),
env| { (vault1.amount(env).unwrap(), vault2.amount(env).unwrap()) },
|state, env| {
let [(_, vault1), (_, vault2)] = &mut state.to_latest_mut().vaults;
(vault1.amount(env).unwrap(), vault2.amount(env).unwrap())
},
)?;
assert_eq!(amount1, dec!("100"));
assert_eq!(amount2, dec!("100"));
Expand Down
4 changes: 1 addition & 3 deletions radix-clis/src/resim/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,7 @@ pub fn get_event_schema<S: SubstateDatabase>(
)
.unwrap()?;

let bp_interface = match bp_definition {
VersionedPackageBlueprintVersionDefinition::V1(blueprint) => blueprint.interface,
};
let bp_interface = bp_definition.into_latest().interface;

let event_def = bp_interface.events.get(event_name)?;
match event_def {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ mod test {
mutable_fields,
} = ds
{
let VersionedSchema::V1(s) = schema;
let s = schema.into_latest();
assert_eq!(s.type_kinds.len(), 1);
assert_eq!(s.type_metadata.len(), 1);
assert_eq!(s.type_validations.len(), 1);
Expand Down
7 changes: 1 addition & 6 deletions radix-engine-tests/tests/kernel/test_environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,7 @@ fn references_read_from_state_are_visible_in_tests1() {
.with_component_state::<VersionedTwoResourcePoolState, _, _, _>(
radiswap_pool_component,
|state, env| {
let VersionedTwoResourcePoolState::V1(
radix_engine::blueprints::pool::v1::substates::two_resource_pool::Substate {
vaults: [(_, vault1), (_, _)],
..
},
) = state;
let [(_, vault1), (_, _)] = &mut state.to_latest_mut().vaults;
vault1.amount(env)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1247,12 +1247,9 @@ impl ConsensusManagerBlueprint {
// then let's be even more accurate here. This sort is stable, so if two validators tie, then the resultant order will be
// decided on sort key DESC.
top_registered_validators.sort_by(|(_, validator_1), (_, validator_2)| {
match (&validator_1.content, &validator_2.content) {
(
VersionedConsensusManagerRegisteredValidatorByStake::V1(validator1),
VersionedConsensusManagerRegisteredValidatorByStake::V1(validator2),
) => validator1.stake.cmp(&validator2.stake).reverse(),
}
let validator1 = validator_1.as_unique_latest_ref();
let validator2 = validator_2.as_unique_latest_ref();
validator1.stake.cmp(&validator2.stake).reverse()
});

let next_active_validator_set = ActiveValidatorSet {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -592,13 +592,42 @@ mod helper_macros {
impl HasLatestVersion for $payload_type_name
{
type Latest = <[<Versioned $ident_core>] as HasLatestVersion>::Latest;

fn is_latest(&self) -> bool {
self.as_ref().is_latest()
}

fn into_latest(self) -> Self::Latest {
self.into_content().into_latest()
}

fn to_latest_mut(&mut self) -> &mut Self::Latest {
self.as_mut().to_latest_mut()
}

fn from_latest(latest: Self::Latest) -> Self {
Self {
content: <[<Versioned $ident_core>] as HasLatestVersion>::from_latest(latest),
}
}

fn as_latest_ref(&self) -> Option<&Self::Latest> {
self.as_ref().as_latest_ref()
}

fn as_latest_mut(&mut self) -> Option<&mut Self::Latest> {
self.as_mut().as_latest_mut()
}
}

impl HasUniqueLatestVersion for $payload_type_name {
fn as_unique_latest_ref(&self) -> &Self::Latest {
self.as_ref().as_unique_latest_ref()
}

fn as_unique_latest_mut(&mut self) -> &mut Self::Latest {
self.as_mut().as_unique_latest_mut()
}
}

// Now implement other relevant content traits, for:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,7 @@ impl MultiResourcePoolBlueprint {
let substate_key = MultiResourcePoolField::State.into();
let handle = api.actor_open_field(ACTOR_STATE_SELF, substate_key, lock_flags)?;
let multi_resource_pool: VersionedMultiResourcePoolState = api.field_read_typed(handle)?;
let multi_resource_pool = match multi_resource_pool {
VersionedMultiResourcePoolState::V1(pool) => pool,
};
let multi_resource_pool = multi_resource_pool.into_latest();

Ok((multi_resource_pool, handle))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,9 @@ impl OneResourcePoolBlueprint {
{
let substate_key = OneResourcePoolField::State.into();
let handle = api.actor_open_field(ACTOR_STATE_SELF, substate_key, lock_flags)?;
let substate = api.field_read_typed::<VersionedOneResourcePoolState>(handle)?;
let substate = match substate {
VersionedOneResourcePoolState::V1(state) => state,
};
let substate = api
.field_read_typed::<VersionedOneResourcePoolState>(handle)?
.into_latest();

Ok((substate, handle))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -595,13 +595,9 @@ impl TwoResourcePoolBlueprint {
{
let substate_key = TwoResourcePoolField::State.into();
let handle = api.actor_open_field(ACTOR_STATE_SELF, substate_key, lock_flags)?;
let two_resource_pool_substate =
api.field_read_typed::<VersionedTwoResourcePoolState>(handle)?;
let two_resource_pool_substate = match two_resource_pool_substate {
VersionedTwoResourcePoolState::V1(two_resource_pool_substate) => {
two_resource_pool_substate
}
};
let two_resource_pool_substate = api
.field_read_typed::<VersionedTwoResourcePoolState>(handle)?
.into_latest();

Ok((two_resource_pool_substate, handle))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ impl RoleAssignmentDatabaseChecker {
F: FnMut(RoleAssignmentDatabaseCheckerError),
{
let key = key.content;
let value = value.content.into_latest();
let value = value.into_latest();

Self::check_access_rule_limits(value, add_error);
Self::check_is_role_key_reserved(&key, add_error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ impl Authorization {
api.kernel_close_substate(handle)?;

match substate.into_value() {
Some(access_rule) => access_rule.content.into_latest(),
Some(access_rule) => access_rule.into_latest(),
None => {
let handle = api.kernel_open_substate(
role_assignment_of.as_node_id(),
Expand Down
1 change: 1 addition & 0 deletions radix-engine/src/vm/wasm/wasmi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1902,6 +1902,7 @@ impl WasmEngine for WasmiEngine {
mod tests {
use super::*;
use wabt::{wat2wasm, wat2wasm_with_features, ErrorKind, Features};
use wasmi::Global;
iamyulong marked this conversation as resolved.
Show resolved Hide resolved

static MODULE_MUTABLE_GLOBALS: &str = r#"
(module
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ impl CommittableSubstateDatabase for RocksDBWithMerkleTreeSubstateStore {
batch.put_cf(
self.cf(MERKLE_NODES_CF),
encode_key(&key),
scrypto_encode(&VersionedTreeNode::new_latest(node)).unwrap(),
scrypto_encode(&VersionedTreeNode::from_latest(node)).unwrap(),
);
}
if !self.pruning_enabled {
Expand Down
8 changes: 2 additions & 6 deletions radix-substate-store-queries/src/query/traverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ impl<'s, 'v, S: SubstateDatabase, V: StateTreeVisitor + 'v> StateTreeTraverser<'
)
.expect("Broken database");

let liquid = match liquid {
VersionedFungibleVaultBalance::V1(liquid) => liquid,
};
let liquid = liquid.into_latest();

visitor.visit_fungible_vault(
node_id,
Expand All @@ -156,9 +154,7 @@ impl<'s, 'v, S: SubstateDatabase, V: StateTreeVisitor + 'v> StateTreeTraverser<'
)
.expect("Broken database");

let liquid = match liquid {
VersionedNonFungibleVaultBalance::V1(liquid) => liquid,
};
let liquid = liquid.into_latest();

visitor.visit_non_fungible_vault(
node_id,
Expand Down
20 changes: 16 additions & 4 deletions sbor-derive-common/src/categorize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,22 @@ fn handle_normal_categorize(
empty_fields_unpacking,
..
} = process_fields_for_encode(&v.fields)?;
Ok((
quote! { Self::#v_id #empty_fields_unpacking => #discriminator, },
quote! { Self::#v_id #empty_fields_unpacking => #unskipped_field_count, },
))

Ok(match discriminator {
VariantDiscriminator::Expr(discriminator) => {
(
quote! { Self::#v_id #empty_fields_unpacking => #discriminator, },
quote! { Self::#v_id #empty_fields_unpacking => #unskipped_field_count, },
)
},
VariantDiscriminator::IgnoreAsUnreachable => {
let panic_message = format!("Variant with index {i} ignored as unreachable");
(
quote! { Self::#v_id #empty_fields_unpacking => panic!(#panic_message), },
quote! { Self::#v_id #empty_fields_unpacking => panic!(#panic_message), },
)
},
})
})
.collect::<Result<Vec<_>>>()?
.into_iter()
Expand Down
15 changes: 12 additions & 3 deletions sbor-derive-common/src/decode.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use itertools::Itertools;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::*;
Expand Down Expand Up @@ -156,12 +157,20 @@ pub fn handle_normal_decode(
let discriminator = &discriminator_mapping[&i];
let decode_fields_content =
decode_fields_content(quote! { Self::#v_id }, &v.fields)?;
Ok(quote! {
#discriminator => {
#decode_fields_content

Ok(match discriminator {
VariantDiscriminator::Expr(discriminator) => Some(quote! {
#discriminator => {
#decode_fields_content
}
}),
VariantDiscriminator::IgnoreAsUnreachable => {
// Don't output any decoder
None
}
})
})
.filter_map_ok(|x| x)
.collect::<Result<Vec<_>>>()?;

// Note: We use #[deny(unreachable_patterns)] to protect against users
Expand Down
95 changes: 52 additions & 43 deletions sbor-derive-common/src/describe.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use itertools::Itertools;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::*;
Expand Down Expand Up @@ -217,53 +218,61 @@ fn handle_normal_describe(
},
Data::Enum(DataEnum { variants, .. }) => {
let discriminator_mapping = get_variant_discriminator_mapping(&attrs, &variants)?;
let variant_discriminators = (0..variants.len())
.into_iter()
.map(|i| &discriminator_mapping[&i])
.collect::<Vec<_>>();

let mut all_field_types = Vec::new();

let variant_type_data: Vec<_> = {
variants
.iter()
.map(|v| {
let variant_name = v.ident.to_string();
let FieldsData {
unskipped_field_types,
unskipped_field_name_strings,
..
} = process_fields_for_describe(&v.fields)?;
all_field_types.extend_from_slice(&unskipped_field_types);
Ok(match &v.fields {
Fields::Named(FieldsNamed { .. }) => {
quote! {
::sbor::TypeData::struct_with_named_fields(
#variant_name,
::sbor::rust::vec![
#((#unskipped_field_name_strings, <#unskipped_field_types as ::sbor::Describe<#custom_type_kind_generic>>::TYPE_ID),)*
],
)
}
let match_arms = variants
.iter()
.enumerate()
.map(|(i, v)| {
let variant_name_str = v.ident.to_string();

let discriminator = match &discriminator_mapping[&i] {
VariantDiscriminator::Expr(d) => d,
VariantDiscriminator::IgnoreAsUnreachable => return Ok(None),
};

let FieldsData {
unskipped_field_types,
unskipped_field_name_strings,
..
} = process_fields_for_describe(&v.fields)?;

all_field_types.extend_from_slice(&unskipped_field_types);

let variant_type_data = match &v.fields {
Fields::Named(FieldsNamed { .. }) => {
quote! {
::sbor::TypeData::struct_with_named_fields(
#variant_name_str,
::sbor::rust::vec![
#((#unskipped_field_name_strings, <#unskipped_field_types as ::sbor::Describe<#custom_type_kind_generic>>::TYPE_ID),)*
],
)
}
Fields::Unnamed(FieldsUnnamed { .. }) => {
quote! {
::sbor::TypeData::struct_with_unnamed_fields(
#variant_name,
::sbor::rust::vec![
#(<#unskipped_field_types as ::sbor::Describe<#custom_type_kind_generic>>::TYPE_ID,)*
],
)
}
}
Fields::Unnamed(FieldsUnnamed { .. }) => {
quote! {
::sbor::TypeData::struct_with_unnamed_fields(
#variant_name_str,
::sbor::rust::vec![
#(<#unskipped_field_types as ::sbor::Describe<#custom_type_kind_generic>>::TYPE_ID,)*
],
)
}
Fields::Unit => {
quote! {
::sbor::TypeData::struct_with_unit_fields(#variant_name)
}
}
Fields::Unit => {
quote! {
::sbor::TypeData::struct_with_unit_fields(#variant_name_str)
}
})
})
.collect::<Result<_>>()?
};
}
};
Ok(Some(quote! {
#discriminator => #variant_type_data,
}))
})
.filter_map_ok(|x| x)
.collect::<Result<Vec<_>>>()?;

let unique_field_types = get_unique_types(&all_field_types);

Expand All @@ -276,7 +285,7 @@ fn handle_normal_describe(
::sbor::TypeData::enum_variants(
#type_name,
::sbor::rust::prelude::indexmap![
#(#variant_discriminators => #variant_type_data,)*
#(#match_arms)*
],
)
}
Expand Down
Loading
Loading