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

Feature/assert next call instructions #1958

Merged
merged 15 commits into from
Oct 17, 2024

Conversation

talekhinezh
Copy link
Member

@talekhinezh talekhinezh commented Oct 14, 2024

  • Implement ASSERT_NEXT_CALL_RETURNS_ONLY and ASSERT_NEXT_CALL_RETURNS_INCLUDE instructions

Copy link

Phylum Report Link

Copy link

github-actions bot commented Oct 14, 2024

Docker tags
docker.io/radixdlt/private-scrypto-builder:2d5e7c91d9

@talekhinezh talekhinezh marked this pull request as ready for review October 14, 2024 00:32
Copy link

github-actions bot commented Oct 14, 2024

Benchmark for 2d5e7c9

Click to view benchmark
Test Base PR %
costing::bench_prepare_wasm 45.0±0.08ms 45.2±0.17ms +0.44%
costing::decode_encoded_i8_array_to_manifest_raw_value 19.6±0.02ms 19.3±0.03ms -1.53%
costing::decode_encoded_i8_array_to_manifest_value 41.4±0.05ms 42.4±0.07ms +2.42%
costing::decode_encoded_tuple_array_to_manifest_raw_value 71.2±0.13ms 72.0±0.12ms +1.12%
costing::decode_encoded_tuple_array_to_manifest_value 104.1±0.15ms 98.3±0.14ms -5.57%
costing::decode_encoded_u8_array_to_manifest_raw_value 26.2±0.05µs 26.6±0.04µs +1.53%
costing::decode_encoded_u8_array_to_manifest_value 41.3±0.05ms 42.4±0.06ms +2.66%
costing::decode_rpd_to_manifest_raw_value 15.0±0.03µs 14.7±0.05µs -2.00%
costing::decode_rpd_to_manifest_value 11.0±0.03µs 11.2±0.05µs +1.82%
costing::deserialize_wasm 1212.6±3.57µs 1228.1±2.65µs +1.28%
costing::execute_transaction_creating_big_vec_substates 700.0±9.72ms 695.6±9.15ms -0.63%
costing::execute_transaction_reading_big_vec_substates 583.9±0.87ms 593.7±0.86ms +1.68%
costing::instantiate_flash_loan 1002.1±1361.67µs 901.7±462.46µs -10.02%
costing::instantiate_radiswap 1138.9±1867.88µs 1018.2±1078.94µs -10.60%
costing::spin_loop 17.7±0.04ms 17.8±0.04ms +0.56%
costing::spin_loop_v2 2.7±0.00s 2.6±0.00s -3.70%
costing::spin_loop_v3 615.3±2.81ms 631.8±0.56ms +2.68%
costing::validate_sbor_payload 30.1±0.03µs 30.0±0.04µs -0.33%
costing::validate_sbor_payload_bytes 245.6±1.37ns 245.9±0.61ns +0.12%
costing::validate_secp256k1 76.6±0.06µs 76.6±0.08µs 0.00%
costing::validate_wasm 34.6±0.04ms 33.9±0.04ms -2.02%
decimal::add/0 8.4±0.00ns 8.4±0.00ns 0.00%
decimal::add/rust-native 9.8±0.01ns 9.8±0.00ns 0.00%
decimal::add/wasmi 219.7±0.53ns 215.0±0.08ns -2.14%
decimal::add/wasmi-call-native 2.1±0.02µs 2.1±0.00µs 0.00%
decimal::div/0 163.8±0.20ns 165.1±0.12ns +0.79%
decimal::from_string/0 163.6±0.42ns 158.2±0.17ns -3.30%
decimal::mul/0 125.9±0.10ns 127.3±0.07ns +1.11%
decimal::mul/rust-native 123.1±0.07ns 123.8±0.09ns +0.57%
decimal::mul/wasmi 11.3±0.28µs 11.6±0.10µs +2.65%
decimal::mul/wasmi-call-native 2.2±0.01µs 2.2±0.00µs 0.00%
decimal::pow/0 574.2±0.29ns 579.3±0.32ns +0.89%
decimal::pow/rust-native 581.5±0.21ns 570.9±0.29ns -1.82%
decimal::pow/wasmi 58.2±0.13µs 57.7±0.23µs -0.86%
decimal::pow/wasmi-call-native 3.1±0.00µs 3.2±0.01µs +3.23%
decimal::root/0 8.1±0.01µs 8.1±0.00µs 0.00%
decimal::sub/0 8.4±0.02ns 8.4±0.03ns 0.00%
decimal::to_string/0 439.0±0.48ns 439.6±0.13ns +0.14%
large_transaction_processing::prepare 2.5±0.00ms 2.6±0.00ms +4.00%
large_transaction_processing::prepare_and_decompile 6.2±0.01ms 6.2±0.03ms 0.00%
large_transaction_processing::prepare_and_decompile_and_recompile 31.9±0.09ms 28.0±1.89ms -12.23%
precise_decimal::add/0 8.8±0.02ns 8.8±0.02ns 0.00%
precise_decimal::add/rust-native 11.0±0.20ns 10.8±0.06ns -1.82%
precise_decimal::add/wasmi 273.8±0.63ns 269.9±0.30ns -1.42%
precise_decimal::add/wasmi-call-native 2.7±0.00µs 2.8±0.00µs +3.70%
precise_decimal::div/0 278.7±0.67ns 278.5±0.28ns -0.07%
precise_decimal::from_string/0 202.4±0.21ns 208.0±0.46ns +2.77%
precise_decimal::mul/0 321.5±0.96ns 327.5±1.47ns +1.87%
precise_decimal::mul/rust-native 289.8±1.29ns 290.5±5.64ns +0.24%
precise_decimal::mul/wasmi 33.5±0.27µs 33.7±0.26µs +0.60%
precise_decimal::mul/wasmi-call-native 3.1±0.00µs 3.1±0.01µs 0.00%
precise_decimal::pow/0 1667.0±1.35ns 1664.3±1.43ns -0.16%
precise_decimal::pow/rust-native 1314.6±0.67ns 1328.4±1.16ns +1.05%
precise_decimal::pow/wasmi 162.9±0.88µs 159.7±1.64µs -1.96%
precise_decimal::pow/wasmi-call-native 5.2±0.01µs 5.3±0.01µs +1.92%
precise_decimal::root/0 58.3±0.03µs 58.0±0.02µs -0.51%
precise_decimal::sub/0 9.0±0.05ns 9.0±0.10ns 0.00%
precise_decimal::to_string/0 687.6±1.36ns 697.8±1.88ns +1.48%
schema::validate_payload 394.0±1.42µs 381.7±0.34µs -3.12%
transaction::radiswap 4.8±0.02ms 4.8±0.02ms 0.00%
transaction::transfer 1824.6±7.48µs 1802.0±2.41µs -1.24%
transaction_validation::validate_manifest 43.1±0.06µs 43.1±0.03µs 0.00%
transaction_validation::verify_bls_2KB 1054.1±23.53µs 1001.2±5.09µs -5.02%
transaction_validation::verify_bls_32B 1038.6±35.80µs 1060.8±12.57µs +2.14%
transaction_validation::verify_ecdsa 74.6±0.06µs 74.5±0.11µs -0.13%
transaction_validation::verify_ed25519 44.6±0.07µs 42.3±0.07µs -5.16%

Copy link
Contributor

@dhedey dhedey left a comment

Choose a reason for hiding this comment

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

Nice. Happy to merge subject to discussion of comments 👍

Ok(())
}
}

struct ResourceConstraintChecker {
fungible_resources: BTreeMap<ResourceAddress, Decimal>,
Copy link
Contributor

Choose a reason for hiding this comment

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

By default, can we use IndexMap unless we have to use an invariant ordering?
IndexMap is more efficient than BTreeMap, and less surprising when things get arbitrarily ordered by byte-ordering of resource address.

Copy link
Member Author

@talekhinezh talekhinezh Oct 15, 2024

Choose a reason for hiding this comment

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

This was originally IndexMap but changed it to use BTreeMap since I want the ability to remove from a map without using swap_remove.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nothing wrong with swap_remove, it's just remove which explains how it affects the ordering.

But yeah, NonIterMap was designed for this purpose. Or if we need to iter, maybe there's some other way to do the algorithm?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah good point, will switch back to IndexMap

objects: &mut IntentProcessorObjects,
_api: &mut Y,
) -> Result<InstructionOutput, RuntimeError> {
objects.next_call_return_constraints = Some(NextCallReturnConstraints {
Copy link
Contributor

Choose a reason for hiding this comment

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

For consistency, perhaps this should be next_call_returns_constraints = Some(NextCallReturnsConstraints ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we should panic or throw an error if this is already set when we set it?

It shouldn't be possible (the validation should enforce it) but sometimes we run transactions without validation (e.g. system transactions).

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it's fine behavior that the system will just override the last setting.

let ids = non_fungible_resources
.remove(&resource_address)
.unwrap_or_default()
.clone();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the clone is unneeded?

Copy link
Member Author

Choose a reason for hiding this comment

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

good catch

}

if exact {
if !fungible_resources.is_empty() || !non_fungible_resources.is_empty() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is only correct if these are all non-zero balances. If this is required, it should IMO be expressed in the parameter name or rust doc. Currently I think this invariant is correctly upheld inside the instruction processor, but it's a little indirect for my liking.

Instead, perhaps we could just iterate across the remaining fungible_resources and non_fungible_resources and if any of the balances are non-zero, then return an error with an example resource? That would then remove this pre-condition; and also allow us to give an example resource which was present.

Copy link
Contributor

Choose a reason for hiding this comment

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

And I think we should add a test for this (to avoid potential regressions in future)

e.g.

  • ASSERT_NEXT_CALL_RETURNS_EXACTLY <empty> and then withdraw XRD Decimal("0") should succeed
  • ASSERT_NEXT_CALL_RETURNS_EXACTLY <empty> and then withdraw <nfs> <empty> should succeed

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, for good regression coverage, would be nice to have a quick test which applies an unmeetable ASSERT_NEXT_CALL_RETURNS_EXACTLY before a CALL_FUNCTION and both YIELD_ commands (and e.g. check it gives a failure)

Copy link
Member Author

Choose a reason for hiding this comment

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

This is only correct if these are all non-zero balances. If this is required, it should IMO be expressed in the parameter name or rust doc. Currently I think this invariant is correctly upheld inside the instruction processor, but it's a little indirect for my liking.

Instead, perhaps we could just iterate across the remaining fungible_resources and non_fungible_resources and if any of the balances are non-zero, then return an error with an example resource? That would then remove this pre-condition; and also allow us to give an example resource which was present.

Good point will fix

Copy link
Member Author

Choose a reason for hiding this comment

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

Also, for good regression coverage, would be nice to have a quick test which applies an unmeetable ASSERT_NEXT_CALL_RETURNS_EXACTLY before a CALL_FUNCTION and both YIELD_ commands (and e.g. check it gives a failure)

This is already covered by tests when_less_is_returned_assert_next_call_returns_only_should_fail and when_more_is_returned_assert_next_call_returns_only_should_fail though it's missing the YIELD_TO_CHILD command. Will add this.

@talekhinezh talekhinezh force-pushed the feature/assert-next-call-instructions branch from e243686 to f4db6d6 Compare October 17, 2024 06:03
@talekhinezh talekhinezh merged commit f0d405c into develop Oct 17, 2024
31 checks passed
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.

2 participants