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

Switch to the typed variants in scrypto lib #1782

Open
wants to merge 28 commits into
base: develop
Choose a base branch
from

Conversation

lrubasze
Copy link
Contributor

@lrubasze lrubasze commented Apr 23, 2024

Summary

Use typed variants in scrypto where possible.
Eg.

  • let claim_royalties() return FungibleBucket instead of Bucket
  • let FungibleVault methods use FungibleBucket
    etc.

Testing

Tests have been updated.

Update Recommendations

For dApp Developers

This is breaking change. Compiler might complain about mismatched types. But in most cases it will also nicely provides a suggested change.
eg.

error[E0308]: mismatched types
  --> radiswap/src/lib.rs:60:13
   |
51 |         ) -> (Bucket, Option<Bucket>) {
   |              ------------------------ expected `(scrypto::prelude::Bucket, std::option::Option<scrypto::prelude::Bucket>)` because of return type
...
60 |             self.pool_component.contribute((resource1, resource2))
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(Bucket, Option<Bucket>)`, found `(FungibleBucket, Option<FungibleBucket>)`
   |
   = note: expected tuple `(scrypto::prelude::Bucket, std::option::Option<scrypto::prelude::Bucket>)`
              found tuple `(scrypto::prelude::FungibleBucket, std::option::Option<scrypto::prelude::FungibleBucket>)`

error[E0308]: mismatched types
   --> radiswap/src/lib.rs:115:51
    |
115 |             self.pool_component.protected_deposit(bucket)
    |                                 ----------------- ^^^^^^ expected `FungibleBucket`, found `Bucket`
    |                                 |
    |                                 arguments to this method are incorrect
    |
note: method defined here
   --> /Users/lukaszrubaszewski/work/radixdlt/radixdlt-scrypto/scrypto/src/component/stubs.rs:315:12
    |
315 |         fn protected_deposit(&mut self, bucket: FungibleBucket);
    |            ^^^^^^^^^^^^^^^^^
help: try wrapping the expression in `scrypto::prelude::FungibleBucket`
    |
115 |             self.pool_component.protected_deposit(scrypto::prelude::FungibleBucket(bucket))
    |                                                   +++++++++++++++++++++++++++++++++      +

error[E0308]: mismatched types
   --> radiswap/src/lib.rs:119:13
    |
118 |           fn withdraw(&mut self, resource_address: ResourceAddress, amount: Decimal) -> Bucket {
    |                                                                                         ------ expected `scrypto::prelude::Bucket` because of return type
119 | /             self.pool_component.protected_withdraw(
120 | |                 resource_address,
121 | |                 amount,
122 | |                 WithdrawStrategy::Rounded(RoundingMode::ToZero),
123 | |             )
    | |_____________^ expected `Bucket`, found `FungibleBucket`
    |
help: call `Into::into` on this expression to convert `scrypto::prelude::FungibleBucket` into `scrypto::prelude::Bucket`
    |
123 |             ).into()
    |              +++++++

Copy link

github-actions bot commented Apr 23, 2024

Docker tags
docker.io/radixdlt/private-scrypto-builder:3caa17c28a

Copy link

github-actions bot commented Apr 23, 2024

Benchmark for 3caa17c

Click to view benchmark
Test Base PR %
costing::bench_prepare_wasm 65.4±0.15ms 65.2±0.18ms -0.31%
costing::decode_sbor 11.2±0.03µs 10.9±0.02µs -2.68%
costing::decode_sbor_bytes 29.5±0.04µs 29.5±0.04µs 0.00%
costing::deserialize_wasm 1267.4±3.97µs 1278.2±25.25µs +0.85%
costing::instantiate_flash_loan 5.6±0.04ms 3.7±0.48ms -33.93%
costing::instantiate_radiswap 5.5±0.05ms 5.6±0.05ms +1.82%
costing::spin_loop 21.7±0.17ms 21.7±0.04ms 0.00%
costing::validate_sbor_payload 30.4±0.05µs 30.0±0.03µs -1.32%
costing::validate_sbor_payload_bytes 261.7±0.74ns 253.8±1.01ns -3.02%
costing::validate_secp256k1 76.2±0.17µs 76.4±0.10µs +0.26%
costing::validate_wasm 36.3±0.05ms 36.4±0.09ms +0.28%
decimal::add/0 8.4±0.00ns 8.4±0.00ns 0.00%
decimal::add/rust-native 9.9±0.01ns 9.9±0.01ns 0.00%
decimal::add/wasmer 122.2±0.31ns 118.4±0.56ns -3.11%
decimal::add/wasmer-call-native 460.4±1.27ns 451.8±0.41ns -1.87%
decimal::add/wasmi 575.4±0.92ns 620.4±5.68ns +7.82%
decimal::add/wasmi-call-native 5.1±0.01µs 5.2±0.01µs +1.96%
decimal::div/0 190.3±0.50ns 190.3±0.27ns 0.00%
decimal::from_string/0 150.3±0.14ns 150.4±0.24ns +0.07%
decimal::mul/0 142.6±0.28ns 142.5±0.06ns -0.07%
decimal::mul/rust-native 139.4±0.21ns 139.5±0.27ns +0.07%
decimal::mul/wasmer 1502.1±0.64ns 1507.7±0.92ns +0.37%
decimal::mul/wasmer-call-native 574.8±0.56ns 620.2±0.78ns +7.90%
decimal::mul/wasmi 41.3±0.23µs 40.9±0.07µs -0.97%
decimal::mul/wasmi-call-native 5.1±0.01µs 5.2±0.02µs +1.96%
decimal::pow/0 653.7±0.37ns 653.5±0.34ns -0.03%
decimal::pow/rust-native 628.8±0.68ns 629.7±0.52ns +0.14%
decimal::pow/wasmer 6.6±0.00µs 6.6±0.01µs 0.00%
decimal::pow/wasmer-call-native 1042.3±3.04ns 1032.7±0.56ns -0.92%
decimal::pow/wasmi 193.2±0.27µs 194.2±0.79µs +0.52%
decimal::pow/wasmi-call-native 5.1±0.01µs 5.1±0.03µs 0.00%
decimal::root/0 7.8±0.03µs 7.8±0.01µs 0.00%
decimal::sub/0 8.5±0.01ns 8.5±0.01ns 0.00%
decimal::to_string/0 442.9±0.20ns 448.2±0.82ns +1.20%
precise_decimal::add/0 9.3±0.12ns 9.4±0.18ns +1.08%
precise_decimal::add/rust-native 11.4±0.00ns 11.4±0.00ns 0.00%
precise_decimal::add/wasmer 116.8±0.13ns 116.6±0.10ns -0.17%
precise_decimal::add/wasmer-call-native 498.1±0.60ns 494.3±0.44ns -0.76%
precise_decimal::add/wasmi 724.7±1.64ns 752.1±3.54ns +3.78%
precise_decimal::add/wasmi-call-native 6.6±0.02µs 6.6±0.01µs 0.00%
precise_decimal::div/0 303.2±0.25ns 303.2±0.12ns 0.00%
precise_decimal::from_string/0 200.7±0.22ns 200.8±0.33ns +0.05%
precise_decimal::mul/0 362.8±10.10ns 360.1±2.28ns -0.74%
precise_decimal::mul/rust-native 303.7±0.31ns 303.8±0.19ns +0.03%
precise_decimal::mul/wasmer 3.4±0.00µs 3.4±0.00µs 0.00%
precise_decimal::mul/wasmer-call-native 811.4±1.39ns 825.0±0.82ns +1.68%
precise_decimal::mul/wasmi 105.5±0.22µs 104.9±0.46µs -0.57%
precise_decimal::mul/wasmi-call-native 7.1±0.01µs 7.1±0.03µs 0.00%
precise_decimal::pow/0 1938.4±2.54ns 1939.2±5.58ns +0.04%
precise_decimal::pow/rust-native 1452.6±6.93ns 1449.1±2.77ns -0.24%
precise_decimal::pow/wasmer 16.2±0.01µs 16.0±0.02µs -1.23%
precise_decimal::pow/wasmer-call-native 2.1±0.00µs 2.1±0.00µs 0.00%
precise_decimal::pow/wasmi 507.3±0.72µs 508.0±0.71µs +0.14%
precise_decimal::pow/wasmi-call-native 13.0±0.08µs 13.0±0.09µs 0.00%
precise_decimal::root/0 56.4±0.03µs 56.4±0.01µs 0.00%
precise_decimal::sub/0 9.5±0.00ns 9.5±0.00ns 0.00%
precise_decimal::to_string/0 722.6±1.33ns 725.5±1.19ns +0.40%
schema::validate_payload 342.2±0.57µs 341.9±0.66µs -0.09%
transaction::radiswap 5.3±0.02ms 5.4±0.02ms +1.89%
transaction::transfer 1749.5±8.00µs 1757.4±11.69µs +0.45%
transaction_processing::prepare 2.2±0.00ms 2.2±0.00ms 0.00%
transaction_processing::prepare_and_decompile 6.1±0.04ms 6.0±0.04ms -1.64%
transaction_processing::prepare_and_decompile_and_recompile 24.1±0.08ms 24.8±1.59ms +2.90%
transaction_validation::validate_manifest 42.1±0.03µs 42.2±0.04µs +0.24%
transaction_validation::verify_bls_2KB 992.0±28.71µs 970.4±7.17µs -2.18%
transaction_validation::verify_bls_32B 971.7±15.77µs 1060.9±95.35µs +9.18%
transaction_validation::verify_ecdsa 74.3±0.05µs 74.1±0.04µs -0.27%
transaction_validation::verify_ed25519 54.8±0.07µs 54.8±0.06µs 0.00%

@lrubasze lrubasze force-pushed the feature/non_fungible_and_fungible_types branch 2 times, most recently from e50c4a4 to 457693b Compare May 1, 2024 13:53
@lrubasze lrubasze force-pushed the feature/non_fungible_and_fungible_types branch from 457693b to a324be3 Compare May 1, 2024 16:11
@lrubasze lrubasze changed the title Feature/non fungible and fungible types Switch to specialised types in scrypto where possible May 1, 2024
@lrubasze lrubasze added the scrypto-lib Any change to the scrypto library label May 1, 2024
@lrubasze lrubasze changed the title Switch to specialised types in scrypto where possible Switch to the typed variants in scrypto lib May 1, 2024
fn claim_xrd(&mut self, bucket: Bucket) -> Bucket;
fn stake_as_owner(&mut self, stake: FungibleBucket) -> FungibleBucket;
fn stake(&mut self, stake: FungibleBucket) -> FungibleBucket;
fn unstake(&mut self, stake_unit_bucket: FungibleBucket) -> FungibleBucket;
Copy link
Member

Choose a reason for hiding this comment

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

I believe that unstake and claim_xrd are not correct.

  • Input to unstake is indeed fungible but the output is a non-fungible claim NFT.
  • Input to claim_xrd is a non-fungible claim NFT and the output is fungible XRD.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, I've mixed it with validator stake units 🤦

fn start_unlock_owner_stake_units(&mut self, requested_stake_unit_amount: Decimal);
fn finish_unlock_owner_stake_units(&mut self) -> Bucket;
fn finish_unlock_owner_stake_units(&mut self) -> FungibleBucket;
fn apply_emission(
Copy link
Member

Choose a reason for hiding this comment

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

Not quite user facing but should apply_reward's bucket be a FungibleBucket?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct

fn lock_fee(&mut self, amount: Decimal);
fn lock_contingent_fee(&mut self, amount: Decimal);
fn deposit(&mut self, bucket: Bucket);
fn deposit_batch(&mut self, buckets: Vec<Bucket>);
fn withdraw(&mut self, resource_address: ResourceAddress, amount: Decimal) -> Bucket;
fn withdraw_non_fungibles(
&mut self,
resource_address: ResourceAddress,
resource_address: NonFungibleBucket,
Copy link
Member

Choose a reason for hiding this comment

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

Probably an accidental mistake, but this should remain to be a ResourceAddress.

Copy link
Member

Choose a reason for hiding this comment

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

It looks like this is an issue with how the function signatures were overriden in update-bindgen.sh.

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 believe the return type should be NonFungibleBucket

@@ -178,14 +179,14 @@ extern_blueprint_internal! {
) -> Bucket;
fn lock_fee_and_withdraw_non_fungibles(
&mut self,
amount_to_lock: Decimal,
amount_to_lock: NonFungibleBucket,
Copy link
Member

Choose a reason for hiding this comment

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

Ditto: seems to have completely changed the type here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack

resource_address: ResourceAddress,
ids: Vec<NonFungibleLocalId>,
) -> Bucket;
fn create_proof_of_amount(&self, resource_address: ResourceAddress, amount: Decimal) -> Proof;
fn create_proof_of_amount(&self, resource_address: FungibleProof, amount: Decimal) -> Proof;
Copy link
Member

Choose a reason for hiding this comment

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

Ditto: seems to have completely changed the type here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack

fn create_proof_of_non_fungibles(
&self,
resource_address: ResourceAddress,
resource_address: NonFungibleProof,
Copy link
Member

Choose a reason for hiding this comment

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

Ditto: seems to have completely changed the type here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack

@@ -239,15 +240,16 @@ extern_blueprint_internal! {
) -> Global<MultiResourcePool>;
},
{
fn contribute(&mut self, buckets: Vec<Bucket>) -> (Bucket, Vec<Bucket>);
fn contribute(&mut self, buckets: Vec<FungibleBucket>)
-> (FungibleBucket, Vec<FungibleBucket>);
fn redeem(&mut self, bucket: Bucket) -> Vec<Bucket>;
Copy link
Member

Choose a reason for hiding this comment

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

I think redeem should be a (FungibleBucket) -> Vec<FungibleBucket> since the input is the pool units (fungible) and the output is fungible resources.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

typo in update-bindings.sh reedem 🤦

fn redeem(&mut self, bucket: Bucket) -> Vec<Bucket>;
fn protected_deposit(&mut self, bucket: Bucket);
fn protected_deposit(&mut self, bucket: FungibleBucket);
fn protected_withdraw(
&mut self,
resource_address: ResourceAddress,
Copy link
Member

Choose a reason for hiding this comment

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

Do we want to double down on the whole fungible and non-fungible bit and make this a FungibleResourceManager?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.
As agreed refactored other parts, where ResourceAddress appears.
Switched to FungibleResourceManager, NonFungibleResourceManager or ResourceManager depending on context.

@@ -274,14 +276,14 @@ extern_blueprint_internal! {
) -> Global<OneResourcePool>;
},
{
fn contribute(&mut self, bucket: Bucket) -> Bucket;
fn contribute(&mut self, bucket: FungibleBucket) -> FungibleBucket;
fn redeem(&mut self, bucket: Bucket) -> Bucket;
Copy link
Member

Choose a reason for hiding this comment

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

Ditto on redeem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack

fn contribute(
&mut self,
buckets: (FungibleBucket, FungibleBucket),
) -> (FungibleBucket, Option<FungibleBucket>);
fn redeem(&mut self, bucket: Bucket) -> (Bucket, Bucket);
Copy link
Member

Choose a reason for hiding this comment

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

Ditto on redeem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack

@@ -382,10 +387,13 @@ extern_blueprint_internal! {
fn quick_confirm_recovery_role_badge_withdraw_attempt(&mut self) -> Bucket;
fn cancel_primary_role_badge_withdraw_attempt(&mut self);
fn cancel_recovery_role_badge_withdraw_attempt(&mut self);
fn mint_recovery_badges(&mut self, non_fungible_local_ids: Vec<NonFungibleLocalId>) -> Bucket;
fn mint_recovery_badges(
Copy link
Member

Choose a reason for hiding this comment

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

This should return a NonFungibleBucket and not a fungible bucket since the recovery badge is non-fungible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

fn lock_fee(&mut self, amount: Decimal);
fn lock_contingent_fee(&mut self, amount: Decimal);
fn deposit(&mut self, bucket: Bucket);
fn deposit_batch(&mut self, buckets: Vec<Bucket>);
fn withdraw(&mut self, resource_address: ResourceAddress, amount: Decimal) -> Bucket;
fn withdraw_non_fungibles(
&mut self,
resource_address: ResourceAddress,
resource_address: NonFungibleBucket,
ids: Vec<NonFungibleLocalId>,
) -> Bucket;
Copy link
Member

Choose a reason for hiding this comment

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

I think that this should return NonFungibleBucket.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's right

Comment on lines 15 to 18
&self,
amount: A,
resource_address: ResourceAddress,
) -> Proof;
) -> FungibleProof;
Copy link
Member

@0xOmarA 0xOmarA May 2, 2024

Choose a reason for hiding this comment

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

Is this true? Is a proof created by amount always fungible? IIRC I don't think that this is correct. I think that a proof of non-fungibles can be created by amount. I think that this is one case where it would be good to add a test to ensure that this is true. A test for this could be: 1. Creating proofs of fungibles by amount works, 2. creating proofs of non-fungibles by amount does not work, therefore we can safely use a FungibleProof here.

Copy link
Contributor Author

@lrubasze lrubasze May 6, 2024

Choose a reason for hiding this comment

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

According to the sources one can create_proof_of_amount of non-fungibles if amount is None (see compose_proof_by_amount), which is never a case, since amount is wrapped with Some.
Thus, realistically, there is no chance to create a non-fungible proof of amount.
Agree, the best is to create a test that will always verify it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

According to the sources one can create_proof_of_amount of non-fungibles if amount is None (see compose_proof_by_amount)

I was wrong, compose_proof_by_amount is able to return non-fungible proof if amount is Some. Will revert this

@lrubasze lrubasze force-pushed the feature/non_fungible_and_fungible_types branch from 2ed034b to 220268f Compare May 7, 2024 12:14
@lrubasze lrubasze marked this pull request as ready for review May 7, 2024 12:50
Copy link
Member

@0xOmarA 0xOmarA left a comment

Choose a reason for hiding this comment

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

Looks good!

fn lock_fee(&mut self, amount: Decimal);
fn lock_contingent_fee(&mut self, amount: Decimal);
fn deposit(&mut self, bucket: Bucket);
fn deposit_batch(&mut self, buckets: Vec<Bucket>);
fn withdraw(&mut self, resource_address: ResourceAddress, amount: Decimal) -> Bucket;
fn withdraw(&mut self, resource_address: ResourceManager, amount: Decimal) -> Bucket;
Copy link
Member

Choose a reason for hiding this comment

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

I was a bit shocked by the change, despite knowing that we're introducing ResourceManager, FungibleResourceManager and NonFungibleResourceManager.

Are we feeling comfortable with replacing resource_address with resource manager? Curious to learn how other people feel about this.

Copy link
Member

Choose a reason for hiding this comment

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

It's interesting. If we're saying that a fungible and non fungible resources are FungibleResourceManager and NonFungibleResourceManager then it makes sense that an undecided resource would be a ResourceManager. But I see your point on this being a bit of a big change.

Copy link
Member

Choose a reason for hiding this comment

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

Perhaps this is one where traits can be useful? As an example, with some changes to the extern_blueprint macro I imagine that we can support resource_address: impl Into<ResourceAddress> which seems like a more correct argument type for this function.

Copy link
Member

Choose a reason for hiding this comment

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

I think in my mind there are two different things: addresses (identifiers) and stubs, similar to component address and Global<T>.

The question is more about if we should use address or stubs for the interfaces.

Stubs would make Scrypto-to-Scrypto interaction easier, as there is no more conversion needed and everything is type checked.

On the other side, manifest developers/readers will need to map resource manager stubs to addresses.

fn contribute(&mut self, buckets: Vec<Bucket>) -> (Bucket, Vec<Bucket>);
fn redeem(&mut self, bucket: Bucket) -> Vec<Bucket>;
fn protected_deposit(&mut self, bucket: Bucket);
fn contribute(&mut self, buckets: Vec<FungibleBucket>)
Copy link
Member

Choose a reason for hiding this comment

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

I think there was some product requirement to support treating non-fungible in a fungible way. @0xOmarA what do you think?

Copy link
Member

Choose a reason for hiding this comment

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

AFAIK pools of non-fungibles was not a product requirement and is actually something that the pools currently reject:

if let ResourceType::NonFungible { .. } = resource_manager.resource_type(api)? {
Err(Error::NonFungibleResourcesAreNotAccepted { resource_address })?
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
scrypto-lib Any change to the scrypto library
Development

Successfully merging this pull request may close these issues.

None yet

3 participants