diff --git a/CHANGELOG.md b/CHANGELOG.md index f9318243b..5c90d6df7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ At the moment this project **does not** adhere to `change_threshold_accounts()` extrinsics got new TDX `quote` related parameters added. - In [#1134](https://github.com/entropyxyz/entropy-core/pull/1134/) the `--no-sync` option was removed. +- In [#1153](https://github.com/entropyxyz/entropy-core/pull/1153/) the program runtime was updated to accept +multiple oracle inputs, this means any programs that were compiled and used need to be recompiled to the new +runtime ### Added - Protocol message versioning ([#1140](https://github.com/entropyxyz/entropy-core/pull/1140)) @@ -31,6 +34,7 @@ At the moment this project **does not** adhere to - Handle PCK certificates ([#1068](https://github.com/entropyxyz/entropy-core/pull/1068)) - Add quote guards to `ServerInfo` related extrinsics ([#1123](https://github.com/entropyxyz/entropy-core/pull/1123/)) - Remove declare synced ([#1134](https://github.com/entropyxyz/entropy-core/pull/1134/)) +- Update programs to accept multiple oracle data ([#1153](https://github.com/entropyxyz/entropy-core/pull/1153/)) ## [0.3.0](https://github.com/entropyxyz/entropy-core/compare/release/v0.2.0...release/v0.3.0) - 2024-10-22 diff --git a/Cargo.lock b/Cargo.lock index d371f0cdb..bed9bc865 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2578,8 +2578,7 @@ dependencies = [ [[package]] name = "entropy-programs-core" version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b5d04ed1473cf2ddf65364adfa473f4f4127132525342e85ca15adf97f2cb9" +source = "git+https://github.com/entropyxyz/programs.git?branch=master#c689ad3d8114eff88bc646d9b200c71f6e14f436" dependencies = [ "getrandom 0.2.15", "serde", @@ -2590,8 +2589,7 @@ dependencies = [ [[package]] name = "entropy-programs-runtime" version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a50c0e3e7224af04d8bebc6994f7428796de5f88861c89291644f2a85a44d3c" +source = "git+https://github.com/entropyxyz/programs.git?branch=master#c689ad3d8114eff88bc646d9b200c71f6e14f436" dependencies = [ "entropy-programs-core", "thiserror 1.0.68", diff --git a/crates/client/entropy_metadata.scale b/crates/client/entropy_metadata.scale index 00e10f14a..4ee7c5dae 100644 Binary files a/crates/client/entropy_metadata.scale and b/crates/client/entropy_metadata.scale differ diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index 98e73bda6..98d8b4b85 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -210,14 +210,14 @@ pub async fn store_program( program: Vec, configuration_interface: Vec, auxiliary_data_interface: Vec, - oracle_data_pointer: Vec, + oracle_data_pointers: Vec>, version_number: u8, ) -> Result<::Hash, ClientError> { let set_program_tx = entropy::tx().programs().set_program( program, configuration_interface, auxiliary_data_interface, - oracle_data_pointer, + BoundedVec(oracle_data_pointers), version_number, ); let in_block = @@ -290,7 +290,7 @@ pub async fn get_accounts( pub async fn get_programs( api: &OnlineClient, rpc: &LegacyRpcMethods, -) -> Result::AccountId>)>, ClientError> { +) -> Result, ClientError> { let block_hash = rpc.chain_get_block_hash(None).await?.ok_or(ClientError::BlockHash)?; let storage_address = entropy::storage().programs().programs_iter(); diff --git a/crates/shared/device_key_proxy.wasm b/crates/shared/device_key_proxy.wasm index b7daf3b12..1e50cb3d7 100755 Binary files a/crates/shared/device_key_proxy.wasm and b/crates/shared/device_key_proxy.wasm differ diff --git a/crates/testing-utils/example_barebones_with_auxilary.wasm b/crates/testing-utils/example_barebones_with_auxilary.wasm index 8a5084582..3eaf5e2a6 100755 Binary files a/crates/testing-utils/example_barebones_with_auxilary.wasm and b/crates/testing-utils/example_barebones_with_auxilary.wasm differ diff --git a/crates/testing-utils/example_custom_hash.wasm b/crates/testing-utils/example_custom_hash.wasm index 9bc00fe38..4a47aad90 100755 Binary files a/crates/testing-utils/example_custom_hash.wasm and b/crates/testing-utils/example_custom_hash.wasm differ diff --git a/crates/testing-utils/faucet_program.wasm b/crates/testing-utils/faucet_program.wasm index cf1da0813..ec535d929 100755 Binary files a/crates/testing-utils/faucet_program.wasm and b/crates/testing-utils/faucet_program.wasm differ diff --git a/crates/testing-utils/infinite_loop.wasm b/crates/testing-utils/infinite_loop.wasm index a19e84182..c8bb9c5a4 100755 Binary files a/crates/testing-utils/infinite_loop.wasm and b/crates/testing-utils/infinite_loop.wasm differ diff --git a/crates/testing-utils/template_barebones.wasm b/crates/testing-utils/template_barebones.wasm index d54d0dcbc..81fa8ecdc 100755 Binary files a/crates/testing-utils/template_barebones.wasm and b/crates/testing-utils/template_barebones.wasm differ diff --git a/crates/testing-utils/template_basic_transaction.wasm b/crates/testing-utils/template_basic_transaction.wasm index 0c95c3303..1c22d3552 100755 Binary files a/crates/testing-utils/template_basic_transaction.wasm and b/crates/testing-utils/template_basic_transaction.wasm differ diff --git a/crates/threshold-signature-server/Cargo.toml b/crates/threshold-signature-server/Cargo.toml index 8ecd5a67d..badfc292c 100644 --- a/crates/threshold-signature-server/Cargo.toml +++ b/crates/threshold-signature-server/Cargo.toml @@ -46,7 +46,7 @@ entropy-protocol={ version="0.3.0", path="../protocol", features=["server"] } entropy-client ={ version="0.3.0", path="../client", default-features=false, features=["native"] } # Programs -entropy-programs-runtime="0.10.0" +entropy-programs-runtime={ git="https://github.com/entropyxyz/programs.git", branch="master" } # Logging tracing ="0.1.37" diff --git a/crates/threshold-signature-server/src/helpers/substrate.rs b/crates/threshold-signature-server/src/helpers/substrate.rs index a23da6503..ee8a27df5 100644 --- a/crates/threshold-signature-server/src/helpers/substrate.rs +++ b/crates/threshold-signature-server/src/helpers/substrate.rs @@ -52,7 +52,7 @@ pub async fn get_program( api: &OnlineClient, rpc: &LegacyRpcMethods, program_pointer: &::Hash, -) -> Result, UserErr> { +) -> Result { let bytecode_address = entropy::storage().programs().programs(program_pointer); let program_info = query_chain(api, rpc, bytecode_address, None) .await? @@ -64,12 +64,17 @@ pub async fn get_program( pub async fn get_oracle_data( api: &OnlineClient, rpc: &LegacyRpcMethods, - program_oracle_data: Vec, -) -> Result, UserErr> { - let oracle_data_call = entropy::storage().oracle().oracle_data(BoundedVec(program_oracle_data)); - let oracle_info = - query_chain(api, rpc, oracle_data_call, None).await?.unwrap_or(BoundedVec(vec![])); - Ok(oracle_info.0) + program_oracle_datas: Vec>, +) -> Result>, UserErr> { + let mut oracle_infos = vec![]; + for program_oracle_data in program_oracle_datas { + let oracle_data_call = + entropy::storage().oracle().oracle_data(BoundedVec(program_oracle_data)); + let oracle_info = + query_chain(api, rpc, oracle_data_call, None).await?.unwrap_or(BoundedVec(vec![])); + oracle_infos.push(oracle_info.0); + } + Ok(oracle_infos) } /// Takes Stash keys and returns validator info from chain diff --git a/crates/threshold-signature-server/src/user/api.rs b/crates/threshold-signature-server/src/user/api.rs index 7f10931d6..c9397de91 100644 --- a/crates/threshold-signature-server/src/user/api.rs +++ b/crates/threshold-signature-server/src/user/api.rs @@ -689,7 +689,7 @@ pub async fn pre_sign_checks( for (i, program_data) in user_details.programs_data.0.iter().enumerate() { let program_info = get_program(api, rpc, &program_data.program_pointer).await?; - let oracle_data = get_oracle_data(api, rpc, program_info.oracle_data_pointer).await?; + let oracle_data = get_oracle_data(api, rpc, program_info.oracle_data_pointers.0).await?; let auxilary_data = auxilary_data_vec[i].as_ref().map(hex::decode).transpose()?; let signature_request = SignatureRequest { message: message.clone(), auxilary_data }; runtime.evaluate( diff --git a/crates/threshold-signature-server/src/user/tests.rs b/crates/threshold-signature-server/src/user/tests.rs index 111efb54f..70affafbe 100644 --- a/crates/threshold-signature-server/src/user/tests.rs +++ b/crates/threshold-signature-server/src/user/tests.rs @@ -1601,13 +1601,17 @@ async fn test_get_oracle_data() { let rpc = get_rpc(&cxt.node_proc.ws_url).await.unwrap(); run_to_block(&rpc, 1).await; - let oracle_data = get_oracle_data(&api, &rpc, "block_number_entropy".encode()).await.unwrap(); + let oracle_data = + get_oracle_data(&api, &rpc, vec!["block_number_entropy".encode()]).await.unwrap(); let current_block = rpc.chain_get_header(None).await.unwrap().unwrap().number; - assert_eq!(current_block.encode(), oracle_data); + assert_eq!(oracle_data.len(), 1); + assert_eq!(current_block.encode(), oracle_data[0]); // fails gracefully - let oracle_data_fail = get_oracle_data(&api, &rpc, "random_heading".encode()).await.unwrap(); - assert_eq!(oracle_data_fail.len(), 0); + let oracle_data_fail = + get_oracle_data(&api, &rpc, vec!["random_heading".encode()]).await.unwrap(); + assert_eq!(oracle_data_fail.len(), 1); + assert_eq!(oracle_data_fail[0].len(), 0); } pub async fn submit_transaction_request( diff --git a/pallets/programs/src/benchmarking.rs b/pallets/programs/src/benchmarking.rs index 81e0cb145..43b726dd8 100644 --- a/pallets/programs/src/benchmarking.rs +++ b/pallets/programs/src/benchmarking.rs @@ -41,19 +41,21 @@ fn assert_last_event(generic_event: ::RuntimeEvent) { benchmarks! { set_program { + let o in 0 .. T::MaxOracleLookups::get(); let program = vec![10]; let configuration_schema = vec![11]; let auxiliary_data_schema = vec![12]; - let oracle_data_pointer = vec![13]; + let oracle_data_pointers = BoundedVec::try_from([vec![13u8; o as usize]].to_vec()).unwrap(); let version_number = 0u8; let mut hash_input: Vec = vec![]; hash_input.extend(&program); hash_input.extend(&configuration_schema); hash_input.extend(&auxiliary_data_schema); - hash_input.extend(&oracle_data_pointer); hash_input.extend(&vec![version_number]); + let (_oracle_length, hash_input_with_oracle) = + ProgramsPallet::::get_length_and_hash_of_oracle(&oracle_data_pointers, hash_input).unwrap(); - let program_hash = T::Hashing::hash(&hash_input); + let program_hash = T::Hashing::hash(&hash_input_with_oracle); let deployer: T::AccountId = whitelisted_caller(); let sig_req_account: T::AccountId = whitelisted_caller(); @@ -65,7 +67,7 @@ benchmarks! { program.clone(), configuration_schema.clone(), auxiliary_data_schema.clone(), - oracle_data_pointer.clone(), + oracle_data_pointers.clone(), version_number ) verify { @@ -75,7 +77,7 @@ benchmarks! { program_hash, configuration_schema, auxiliary_data_schema, - oracle_data_pointer, + oracle_data_pointers, version_number }.into() ); @@ -83,26 +85,29 @@ benchmarks! { remove_program { let p in 0..T::MaxOwnedPrograms::get(); + let o in 0 .. T::MaxOracleLookups::get(); + let program = vec![10]; let configuration_schema = vec![11]; let auxiliary_data_schema = vec![12]; - let oracle_data_pointer = vec![13]; + let oracle_data_pointers = BoundedVec::try_from([vec![13u8; o as usize]].to_vec()).unwrap(); let version_number = 0u8; let mut hash_input: Vec = vec![]; hash_input.extend(&program); hash_input.extend(&configuration_schema); hash_input.extend(&auxiliary_data_schema); - hash_input.extend(&oracle_data_pointer); hash_input.extend(&vec![version_number]); + let (_oracle_length, hash_input_with_oracle) = + ProgramsPallet::::get_length_and_hash_of_oracle(&oracle_data_pointers, hash_input).unwrap(); - let program_hash = T::Hashing::hash(&hash_input); + let program_hash = T::Hashing::hash(&hash_input_with_oracle); let random_program = vec![11]; let random_hash = T::Hashing::hash(&random_program); let deployer: T::AccountId = whitelisted_caller(); let value = CurrencyOf::::minimum_balance().saturating_mul(1_000_000_000u32.into()); let _ = CurrencyOf::::make_free_balance_be(&deployer, value); - >::insert(program_hash.clone(), ProgramInfo {bytecode: program, configuration_schema, auxiliary_data_schema, oracle_data_pointer, deployer: deployer.clone(), ref_counter: 0u128, version_number}); + >::insert(program_hash.clone(), ProgramInfo {bytecode: program, configuration_schema, auxiliary_data_schema, oracle_data_pointers, deployer: deployer.clone(), ref_counter: 0u128, version_number}); let mut program_hashes = vec![random_hash.clone(); p as usize]; // remove one to make room for the targetted removal program hash program_hashes.pop(); diff --git a/pallets/programs/src/lib.rs b/pallets/programs/src/lib.rs index 5e061278d..bdf61e4c5 100644 --- a/pallets/programs/src/lib.rs +++ b/pallets/programs/src/lib.rs @@ -75,6 +75,9 @@ pub mod pallet { /// The maximum amount of owned programs. type MaxOwnedPrograms: Get; + /// The maximum amount of oracle lookups allowed. + type MaxOracleLookups: Get; + /// The amount to charge, per byte, for storing a program on-chain. type ProgramDepositPerByte: Get>; @@ -85,6 +88,8 @@ pub mod pallet { type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; + pub type OraclePointers = BoundedVec, ::MaxOracleLookups>; + #[pallet::genesis_config] #[derive(frame_support::DefaultNoBound)] pub struct GenesisConfig { @@ -108,7 +113,7 @@ pub mod pallet { configuration_schema: program_info.2.clone(), auxiliary_data_schema: program_info.3.clone(), deployer: program_info.4.clone(), - oracle_data_pointer: vec![], + oracle_data_pointers: BoundedVec::try_from([].to_vec()).unwrap(), ref_counter: program_info.5, version_number: 0, }, @@ -123,7 +128,8 @@ pub mod pallet { /// Information on the program #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)] - pub struct ProgramInfo { + #[scale_info(skip_type_params(T))] + pub struct ProgramInfo { /// The bytecode of the program. pub bytecode: Vec, /// The schema for the Program's configuration parameters. @@ -138,10 +144,10 @@ pub mod pallet { /// [JSON Schema](https://json-schema.org/) in order to simplify the life of off-chain /// actors. pub auxiliary_data_schema: Vec, - /// The location of the oracle data needed for this program - pub oracle_data_pointer: Vec, + /// The locations of the oracle data needed for this program + pub oracle_data_pointers: OraclePointers, /// Deployer of the program - pub deployer: AccountId, + pub deployer: T::AccountId, /// Accounts that use this program pub ref_counter: u128, /// The user submitted version number of the program's runtime @@ -154,7 +160,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn programs)] pub type Programs = - StorageMap<_, Blake2_128Concat, T::Hash, ProgramInfo, OptionQuery>; + StorageMap<_, Blake2_128Concat, T::Hash, ProgramInfo, OptionQuery>; /// Maps an account to all the programs it owns #[pallet::storage] @@ -184,8 +190,8 @@ pub mod pallet { /// The new program auxiliary data schema. auxiliary_data_schema: Vec, - /// The oracle data location needed for the program - oracle_data_pointer: Vec, + /// The oracle data locations needed for the program + oracle_data_pointers: OraclePointers, /// The version number of runtime for which the program was written version_number: u8, @@ -224,30 +230,33 @@ pub mod pallet { /// /// Note that the caller becomes the deployer account. #[pallet::call_index(0)] - #[pallet::weight({::WeightInfo::set_program()})] + #[pallet::weight({::WeightInfo::set_program(::MaxOracleLookups::get())})] pub fn set_program( origin: OriginFor, new_program: Vec, configuration_schema: Vec, auxiliary_data_schema: Vec, - oracle_data_pointer: Vec, + oracle_data_pointers: OraclePointers, version_number: u8, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let deployer = ensure_signed(origin)?; let mut hash_input = vec![]; hash_input.extend(&new_program); hash_input.extend(&configuration_schema); hash_input.extend(&auxiliary_data_schema); - hash_input.extend(&oracle_data_pointer); + hash_input.extend(&vec![version_number]); - let program_hash = T::Hashing::hash(&hash_input); + let (oracle_length, hash_input_with_oracle) = + Self::get_length_and_hash_of_oracle(&oracle_data_pointers, hash_input)?; + let program_hash = T::Hashing::hash(&hash_input_with_oracle); + let new_program_length = new_program .len() .checked_add(configuration_schema.len()) .ok_or(Error::::ArithmeticError)? .checked_add(auxiliary_data_schema.len()) .ok_or(Error::::ArithmeticError)? - .checked_add(oracle_data_pointer.len()) + .checked_add(oracle_length) .ok_or(Error::::ArithmeticError)?; ensure!( new_program_length as u32 <= T::MaxBytecodeLength::get(), @@ -263,7 +272,7 @@ pub mod pallet { bytecode: new_program.clone(), configuration_schema: configuration_schema.clone(), auxiliary_data_schema: auxiliary_data_schema.clone(), - oracle_data_pointer: oracle_data_pointer.clone(), + oracle_data_pointers: oracle_data_pointers.clone(), deployer: deployer.clone(), ref_counter: 0u128, version_number, @@ -283,17 +292,18 @@ pub mod pallet { program_hash, configuration_schema, auxiliary_data_schema, - oracle_data_pointer, + oracle_data_pointers: oracle_data_pointers.clone(), version_number, }); - Ok(()) + Ok(Some(::WeightInfo::set_program(oracle_data_pointers.len() as u32)) + .into()) } /// Removes a program at a specific hash /// /// Caller must be the deployer account for said program. #[pallet::call_index(1)] - #[pallet::weight({::WeightInfo::remove_program( ::MaxOwnedPrograms::get())})] + #[pallet::weight({::WeightInfo::remove_program( ::MaxOracleLookups::get(), ::MaxOwnedPrograms::get())})] pub fn remove_program( origin: OriginFor, program_hash: T::Hash, @@ -303,12 +313,18 @@ pub mod pallet { Self::programs(program_hash).ok_or(Error::::NoProgramDefined)?; ensure!(old_program_info.deployer == deployer, Error::::NotAuthorized); ensure!(old_program_info.ref_counter == 0, Error::::ProgramInUse); + + let mut oracle_length: usize = 0; + for oracle_data_pointer in &old_program_info.oracle_data_pointers { + oracle_length += oracle_data_pointer.len(); + } + Self::unreserve_program_deposit( &old_program_info.deployer, old_program_info.bytecode.len() + old_program_info.configuration_schema.len() + old_program_info.auxiliary_data_schema.len() - + old_program_info.oracle_data_pointer.len(), + + oracle_length, ); let mut owned_programs_length = 0; OwnedPrograms::::try_mutate( @@ -325,7 +341,11 @@ pub mod pallet { )?; Programs::::remove(program_hash); Self::deposit_event(Event::ProgramRemoved { deployer, old_program_hash: program_hash }); - Ok(Some(::WeightInfo::remove_program(owned_programs_length as u32)).into()) + Ok(Some(::WeightInfo::remove_program( + old_program_info.oracle_data_pointers.len() as u32, + owned_programs_length as u32, + )) + .into()) } } @@ -372,5 +392,19 @@ pub mod pallet { Ok(()) } + + /// Gets hash input and length of each oracle data pointer + pub fn get_length_and_hash_of_oracle( + oracle_datas: &OraclePointers, + mut hash_input: Vec, + ) -> Result<(usize, Vec), Error> { + let mut length: usize = 0; + for oracle_data in oracle_datas { + hash_input.extend(oracle_data); + length = + length.checked_add(oracle_data.len()).ok_or(Error::::ArithmeticError)?; + } + Ok((length, hash_input)) + } } } diff --git a/pallets/programs/src/mock.rs b/pallets/programs/src/mock.rs index 8d4891333..20ece9a7b 100644 --- a/pallets/programs/src/mock.rs +++ b/pallets/programs/src/mock.rs @@ -71,6 +71,7 @@ parameter_types! { pub const MaxBytecodeLength: u32 = 5; pub const ProgramDepositPerByte: u32 = 5; pub const MaxOwnedPrograms: u32 = 1; + pub const MaxOracleLookups: u32 = 2; } parameter_types! { @@ -99,6 +100,7 @@ impl pallet_programs::Config for Test { type MaxBytecodeLength = MaxBytecodeLength; type ProgramDepositPerByte = ProgramDepositPerByte; type MaxOwnedPrograms = MaxOwnedPrograms; + type MaxOracleLookups = MaxOracleLookups; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } diff --git a/pallets/programs/src/tests.rs b/pallets/programs/src/tests.rs index d930b7acd..365e12025 100644 --- a/pallets/programs/src/tests.rs +++ b/pallets/programs/src/tests.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use frame_support::{assert_noop, assert_ok, traits::Currency}; +use frame_support::{assert_noop, assert_ok, traits::Currency, BoundedVec}; use pallet_balances::Error as BalancesError; use sp_runtime::traits::Hash; @@ -29,17 +29,19 @@ fn set_program() { let program_2 = vec![12u8, 13u8]; let configuration_schema = vec![14u8]; let auxiliary_data_schema = vec![15u8]; - let oracle_data_pointer = vec![16u8]; + let oracle_data_pointers = BoundedVec::try_from([vec![16u8]].to_vec()).unwrap(); let version_number = 0u8; let too_long = vec![1u8, 2u8, 3u8, 4u8, 5u8]; let mut hash_input: Vec = vec![]; hash_input.extend(&program); hash_input.extend(&configuration_schema); hash_input.extend(&auxiliary_data_schema); - hash_input.extend(&oracle_data_pointer); hash_input.extend(&vec![version_number]); + let (_oracle_length, hash_input_with_oracle) = + ProgramsPallet::get_length_and_hash_of_oracle(&oracle_data_pointers, hash_input) + .unwrap(); - let program_hash = ::Hashing::hash(&hash_input); + let program_hash = ::Hashing::hash(&hash_input_with_oracle); // can't pay deposit assert_noop!( ProgramsPallet::set_program( @@ -47,7 +49,7 @@ fn set_program() { program.clone(), configuration_schema.clone(), auxiliary_data_schema.clone(), - oracle_data_pointer.clone(), + oracle_data_pointers.clone(), version_number ), BalancesError::::InsufficientBalance @@ -60,14 +62,14 @@ fn set_program() { program.clone(), configuration_schema.clone(), auxiliary_data_schema.clone(), - oracle_data_pointer.clone(), + oracle_data_pointers.clone(), version_number )); let program_result = ProgramInfo { bytecode: program.clone(), configuration_schema: configuration_schema.clone(), auxiliary_data_schema: auxiliary_data_schema.clone(), - oracle_data_pointer: oracle_data_pointer.clone(), + oracle_data_pointers: oracle_data_pointers.clone(), deployer: PROGRAM_MODIFICATION_ACCOUNT, ref_counter: 0u128, version_number, @@ -92,7 +94,7 @@ fn set_program() { program.clone(), configuration_schema.clone(), auxiliary_data_schema.clone(), - oracle_data_pointer.clone(), + oracle_data_pointers.clone(), version_number ), Error::::ProgramAlreadySet @@ -105,7 +107,7 @@ fn set_program() { program_2.clone(), configuration_schema.clone(), auxiliary_data_schema.clone(), - oracle_data_pointer.clone(), + oracle_data_pointers.clone(), version_number ), Error::::TooManyProgramsOwned @@ -117,7 +119,7 @@ fn set_program() { too_long, configuration_schema, auxiliary_data_schema.clone(), - oracle_data_pointer.clone(), + oracle_data_pointers.clone(), version_number ), Error::::ProgramLengthExceeded @@ -131,15 +133,18 @@ fn remove_program() { let program = vec![10u8, 11u8]; let configuration_schema = vec![14u8]; let auxiliary_data_schema = vec![15u8]; - let oracle_data_pointer = vec![16u8]; + let oracle_data_pointers = BoundedVec::try_from([vec![16u8]].to_vec()).unwrap(); let version_number = 0u8; let mut hash_input: Vec = vec![]; hash_input.extend(&program); hash_input.extend(&configuration_schema); hash_input.extend(&auxiliary_data_schema); - hash_input.extend(&oracle_data_pointer); hash_input.extend(&vec![version_number]); - let program_hash = ::Hashing::hash(&hash_input); + + let (_oracle_length, hash_input_with_oracle) = + ProgramsPallet::get_length_and_hash_of_oracle(&oracle_data_pointers, hash_input) + .unwrap(); + let program_hash = ::Hashing::hash(&hash_input_with_oracle); // no program assert_noop!( @@ -157,7 +162,7 @@ fn remove_program() { program.clone(), configuration_schema.clone(), auxiliary_data_schema.clone(), - oracle_data_pointer.clone(), + oracle_data_pointers.clone(), version_number )); assert_eq!( @@ -206,7 +211,7 @@ fn remove_program_fails_ref_count() { let program_hash = ::Hashing::hash(&program); let configuration_schema = vec![14u8]; let auxiliary_data_schema = vec![15u8]; - let oracle_data_pointer = vec![16u8]; + let oracle_data_pointers = BoundedVec::try_from([vec![16u8]].to_vec()).unwrap(); let version_number = 0u8; Programs::::insert( @@ -215,7 +220,7 @@ fn remove_program_fails_ref_count() { bytecode: program, configuration_schema, auxiliary_data_schema, - oracle_data_pointer, + oracle_data_pointers, deployer: PROGRAM_MODIFICATION_ACCOUNT, ref_counter: 1u128, version_number, diff --git a/pallets/programs/src/weights.rs b/pallets/programs/src/weights.rs index 2a8934e95..29e3f509d 100644 --- a/pallets/programs/src/weights.rs +++ b/pallets/programs/src/weights.rs @@ -52,79 +52,85 @@ use core::marker::PhantomData; /// Weight functions needed for pallet_programs. pub trait WeightInfo { - fn set_program() -> Weight; - fn remove_program(p: u32) -> Weight; + fn set_program(o: u32) -> Weight; + fn remove_program(o: u32, p: u32) -> Weight; } /// Weights for pallet_programs using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Programs::Bytecode` (r:1 w:1) - /// Proof: `Programs::Bytecode` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Programs::Programs` (r:1 w:1) + /// Proof: `Programs::Programs` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Programs::OwnedPrograms` (r:1 w:1) /// Proof: `Programs::OwnedPrograms` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn set_program() -> Weight { + /// The range of component `o` is `[0, 10]`. + fn set_program(_o: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `3607` - // Minimum execution time: 26_000_000 picoseconds. - Weight::from_parts(27_000_000, 0) - .saturating_add(Weight::from_parts(0, 3607)) + // Measured: `214` + // Estimated: `3679` + // Minimum execution time: 23_000_000 picoseconds. + Weight::from_parts(26_554_140, 0) + .saturating_add(Weight::from_parts(0, 3679)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Programs::Bytecode` (r:1 w:1) - /// Proof: `Programs::Bytecode` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Programs::Programs` (r:1 w:1) + /// Proof: `Programs::Programs` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Programs::OwnedPrograms` (r:1 w:1) /// Proof: `Programs::OwnedPrograms` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `p` is `[0, 25]`. - fn remove_program(p: u32, ) -> Weight { + /// The range of component `p` is `[0, 250]`. + /// The range of component `o` is `[0, 10]`. + fn remove_program(p: u32, o: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `326 + p * (32 ±0)` - // Estimated: `3809 + p * (31 ±0)` - // Minimum execution time: 26_000_000 picoseconds. - Weight::from_parts(26_938_669, 0) - .saturating_add(Weight::from_parts(0, 3809)) - // Standard Error: 47_904 - .saturating_add(Weight::from_parts(136_174, 0).saturating_mul(p.into())) + // Measured: `353 + o * (1 ±0) + p * (32 ±0)` + // Estimated: `3842 + o * (1 ±0) + p * (32 ±0)` + // Minimum execution time: 22_000_000 picoseconds. + Weight::from_parts(28_023_735, 0) + .saturating_add(Weight::from_parts(0, 3842)) + // Standard Error: 11_641 + .saturating_add(Weight::from_parts(103_353, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) - .saturating_add(Weight::from_parts(0, 31).saturating_mul(p.into())) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) + .saturating_add(Weight::from_parts(0, 32).saturating_mul(p.into())) } } // For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Programs::Bytecode` (r:1 w:1) - /// Proof: `Programs::Bytecode` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Programs::Programs` (r:1 w:1) + /// Proof: `Programs::Programs` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Programs::OwnedPrograms` (r:1 w:1) /// Proof: `Programs::OwnedPrograms` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn set_program() -> Weight { + /// The range of component `o` is `[0, 10]`. + fn set_program(_o: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `3607` - // Minimum execution time: 26_000_000 picoseconds. - Weight::from_parts(27_000_000, 0) - .saturating_add(Weight::from_parts(0, 3607)) + // Measured: `214` + // Estimated: `3679` + // Minimum execution time: 23_000_000 picoseconds. + Weight::from_parts(26_554_140, 0) + .saturating_add(Weight::from_parts(0, 3679)) .saturating_add(RocksDbWeight::get().reads(2)) .saturating_add(RocksDbWeight::get().writes(2)) } - /// Storage: `Programs::Bytecode` (r:1 w:1) - /// Proof: `Programs::Bytecode` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Programs::Programs` (r:1 w:1) + /// Proof: `Programs::Programs` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Programs::OwnedPrograms` (r:1 w:1) /// Proof: `Programs::OwnedPrograms` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `p` is `[0, 25]`. - fn remove_program(p: u32, ) -> Weight { + /// The range of component `p` is `[0, 250]`. + /// The range of component `o` is `[0, 10]`. + fn remove_program(p: u32, o: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `326 + p * (32 ±0)` - // Estimated: `3809 + p * (31 ±0)` - // Minimum execution time: 26_000_000 picoseconds. - Weight::from_parts(26_938_669, 0) - .saturating_add(Weight::from_parts(0, 3809)) - // Standard Error: 47_904 - .saturating_add(Weight::from_parts(136_174, 0).saturating_mul(p.into())) + // Measured: `353 + o * (1 ±0) + p * (32 ±0)` + // Estimated: `3842 + o * (1 ±0) + p * (32 ±0)` + // Minimum execution time: 22_000_000 picoseconds. + Weight::from_parts(28_023_735, 0) + .saturating_add(Weight::from_parts(0, 3842)) + // Standard Error: 11_641 + .saturating_add(Weight::from_parts(103_353, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2)) .saturating_add(RocksDbWeight::get().writes(2)) - .saturating_add(Weight::from_parts(0, 31).saturating_mul(p.into())) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) + .saturating_add(Weight::from_parts(0, 32).saturating_mul(p.into())) } } diff --git a/pallets/propagation/src/mock.rs b/pallets/propagation/src/mock.rs index 424010c8b..0478e0197 100644 --- a/pallets/propagation/src/mock.rs +++ b/pallets/propagation/src/mock.rs @@ -351,6 +351,7 @@ parameter_types! { pub const MaxBytecodeLength: u32 = 3; pub const ProgramDepositPerByte: u32 = 5; pub const MaxOwnedPrograms: u32 = 5; + pub const MaxOracleLookups: u32 = 5; } impl pallet_programs::Config for Test { @@ -358,6 +359,7 @@ impl pallet_programs::Config for Test { type MaxBytecodeLength = MaxBytecodeLength; type ProgramDepositPerByte = ProgramDepositPerByte; type MaxOwnedPrograms = MaxOwnedPrograms; + type MaxOracleLookups = MaxOracleLookups; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } diff --git a/pallets/registry/src/benchmarking.rs b/pallets/registry/src/benchmarking.rs index dee1c07f2..65849c535 100644 --- a/pallets/registry/src/benchmarking.rs +++ b/pallets/registry/src/benchmarking.rs @@ -22,7 +22,7 @@ use frame_support::{ BoundedVec, }; use frame_system::{EventRecord, RawOrigin}; -use pallet_programs::{ProgramInfo, Programs}; +use pallet_programs::{OraclePointers, ProgramInfo, Programs}; use pallet_session::Validators; use pallet_staking_extension::{ benchmarking::create_validators, JumpStartDetails, JumpStartProgress, JumpStartStatus, @@ -165,7 +165,7 @@ benchmarks! { let program = vec![0u8]; let configuration_schema = vec![1u8]; let auxiliary_data_schema = vec![2u8]; - let oracle_data_pointer = vec![3u8]; + let oracle_data_pointers: OraclePointers = BoundedVec::try_from([vec![3u8]].to_vec()).unwrap(); let program_hash = T::Hashing::hash(&program); let programs_info = BoundedVec::try_from(vec![ ProgramInstance { @@ -182,7 +182,7 @@ benchmarks! { bytecode: program, configuration_schema, auxiliary_data_schema, - oracle_data_pointer, + oracle_data_pointers, deployer: program_modification_account.clone(), ref_counter: 0, version_number: 0, @@ -251,7 +251,7 @@ benchmarks! { let program = vec![0u8]; let configuration_schema = vec![1u8]; let auxiliary_data_schema = vec![2u8]; - let oracle_data_pointer = vec![3u8]; + let oracle_data_pointers: OraclePointers = BoundedVec::try_from([vec![3u8]].to_vec()).unwrap(); let program_hash = T::Hashing::hash(&program); let programs_info = BoundedVec::try_from(vec![ProgramInstance { program_pointer: program_hash, @@ -266,8 +266,8 @@ benchmarks! { }; n as usize]) .unwrap(); let sig_req_account: T::AccountId = whitelisted_caller(); - Programs::::insert(program_hash, ProgramInfo {bytecode: program, configuration_schema: configuration_schema.clone(), auxiliary_data_schema: auxiliary_data_schema.clone(), oracle_data_pointer: oracle_data_pointer.clone(), deployer: program_modification_account.clone(), ref_counter: 0, version_number: 0}); - Programs::::insert(new_program_hash, ProgramInfo {bytecode: new_program, configuration_schema, auxiliary_data_schema, oracle_data_pointer, deployer: program_modification_account.clone(), ref_counter: o as u128, version_number: 0}); + Programs::::insert(program_hash, ProgramInfo {bytecode: program, configuration_schema: configuration_schema.clone(), auxiliary_data_schema: auxiliary_data_schema.clone(), oracle_data_pointers: oracle_data_pointers.clone(), deployer: program_modification_account.clone(), ref_counter: 0, version_number: 0}); + Programs::::insert(new_program_hash, ProgramInfo {bytecode: new_program, configuration_schema, auxiliary_data_schema, oracle_data_pointers, deployer: program_modification_account.clone(), ref_counter: o as u128, version_number: 0}); let balance = ::Currency::minimum_balance() * 100u32.into(); let _ = ::Currency::make_free_balance_be(&sig_req_account, balance); >::insert( @@ -291,7 +291,7 @@ benchmarks! { let program = vec![0u8]; let configuration_schema = vec![1u8]; let auxiliary_data_schema = vec![2u8]; - let oracle_data_pointer = vec![3u8]; + let oracle_data_pointers: OraclePointers = BoundedVec::try_from([vec![3u8]].to_vec()).unwrap(); let program_hash = T::Hashing::hash(&program); let programs_info = BoundedVec::try_from(vec![ProgramInstance { program_pointer: program_hash, diff --git a/pallets/registry/src/mock.rs b/pallets/registry/src/mock.rs index ad5b26c3b..c46aa88e8 100644 --- a/pallets/registry/src/mock.rs +++ b/pallets/registry/src/mock.rs @@ -348,6 +348,7 @@ parameter_types! { pub const MaxBytecodeLength: u32 = 3; pub const ProgramDepositPerByte: u32 = 5; pub const MaxOwnedPrograms: u32 = 5; + pub const MaxOracleLookups: u32 = 5; } impl pallet_programs::Config for Test { @@ -355,6 +356,7 @@ impl pallet_programs::Config for Test { type MaxBytecodeLength = MaxBytecodeLength; type ProgramDepositPerByte = ProgramDepositPerByte; type MaxOwnedPrograms = MaxOwnedPrograms; + type MaxOracleLookups = MaxOracleLookups; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } diff --git a/pallets/registry/src/tests.rs b/pallets/registry/src/tests.rs index f382bd34c..206f7ce4f 100644 --- a/pallets/registry/src/tests.rs +++ b/pallets/registry/src/tests.rs @@ -43,7 +43,8 @@ fn setup_programs( bytecode: empty_program.clone(), configuration_schema: empty_program.clone(), auxiliary_data_schema: empty_program.clone(), - oracle_data_pointer: empty_program.clone(), + oracle_data_pointers: BoundedVec::try_from(vec![empty_program.clone()].to_vec()) + .unwrap(), deployer: alice, ref_counter: 0, version_number: 0, @@ -479,7 +480,8 @@ fn it_changes_a_program_instance() { bytecode: empty_program.clone(), configuration_schema: empty_program.clone(), auxiliary_data_schema: empty_program.clone(), - oracle_data_pointer: empty_program.clone(), + oracle_data_pointers: BoundedVec::try_from(vec![empty_program.clone()].to_vec()) + .unwrap(), deployer: 1, ref_counter: 1, version_number: 0, @@ -500,7 +502,8 @@ fn it_changes_a_program_instance() { bytecode: new_program, configuration_schema: empty_program.clone(), auxiliary_data_schema: empty_program.clone(), - oracle_data_pointer: empty_program.clone(), + oracle_data_pointers: BoundedVec::try_from(vec![empty_program.clone()].to_vec()) + .unwrap(), deployer: 1, ref_counter: 1, version_number: 0, diff --git a/pallets/transaction-pause/src/mock.rs b/pallets/transaction-pause/src/mock.rs index 5cc9a2c58..961defb8b 100644 --- a/pallets/transaction-pause/src/mock.rs +++ b/pallets/transaction-pause/src/mock.rs @@ -86,6 +86,7 @@ parameter_types! { pub const MaxBytecodeLength: u32 = 3; pub const ProgramDepositPerByte: u32 = 5; pub const MaxOwnedPrograms: u32 = 5; + pub const MaxOracleLookups: u32 = 5; } impl pallet_programs::Config for Runtime { @@ -93,6 +94,7 @@ impl pallet_programs::Config for Runtime { type MaxBytecodeLength = MaxBytecodeLength; type ProgramDepositPerByte = ProgramDepositPerByte; type MaxOwnedPrograms = MaxOwnedPrograms; + type MaxOracleLookups = MaxOracleLookups; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } diff --git a/pallets/transaction-pause/src/tests.rs b/pallets/transaction-pause/src/tests.rs index 7ac70ed75..b1c822d75 100644 --- a/pallets/transaction-pause/src/tests.rs +++ b/pallets/transaction-pause/src/tests.rs @@ -152,7 +152,7 @@ fn paused_transaction_filter_work() { new_program: vec![], configuration_schema: vec![], auxiliary_data_schema: vec![], - oracle_data_pointer: vec![], + oracle_data_pointers: BoundedVec::try_from(vec![vec![]].to_vec()).unwrap(), version_number: 0u8, }); assert!(!PausedTransactionFilter::::contains(BALANCE_TRANSFER)); diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index f801c6a94..461a4d49d 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1467,6 +1467,7 @@ parameter_types! { pub const MaxBytecodeLength: u32 = 1_000_000; pub const ProgramDepositPerByte: Balance = MILLICENTS; pub const MaxOwnedPrograms: u32 = 250; + pub const MaxOracleLookups: u32 = 10; } impl pallet_programs::Config for Runtime { @@ -1474,6 +1475,7 @@ impl pallet_programs::Config for Runtime { type MaxBytecodeLength = MaxBytecodeLength; type ProgramDepositPerByte = ProgramDepositPerByte; type MaxOwnedPrograms = MaxOwnedPrograms; + type MaxOracleLookups = MaxOracleLookups; type RuntimeEvent = RuntimeEvent; type WeightInfo = weights::pallet_programs::WeightInfo; } diff --git a/runtime/src/weights/pallet_programs.rs b/runtime/src/weights/pallet_programs.rs index dc006272f..f9519b473 100644 --- a/runtime/src/weights/pallet_programs.rs +++ b/runtime/src/weights/pallet_programs.rs @@ -16,9 +16,9 @@ //! Autogenerated weights for `pallet_programs` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 33.0.0 -//! DATE: 2024-10-03, STEPS: `25`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-11-08, STEPS: `5`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ip-172-31-28-93`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! HOSTNAME: `Jesses-MacBook-Pro.local`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: 1024 // Executed Command: @@ -27,14 +27,11 @@ // pallet // --chain // dev -// --wasm-execution=compiled // --pallet=pallet_programs // --extrinsic=* -// --steps=25 -// --repeat=10 +// --steps=5 +// --repeat=2 // --header=.maintain/AGPL-3.0-header.txt -// --template -// .maintain/frame-weight-template.hbs // --output=./runtime/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] @@ -52,12 +49,13 @@ impl pallet_programs::WeightInfo for WeightInfo { /// Proof: `Programs::Programs` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Programs::OwnedPrograms` (r:1 w:1) /// Proof: `Programs::OwnedPrograms` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn set_program() -> Weight { + /// The range of component `o` is `[0, 10]`. + fn set_program(_o: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `214` // Estimated: `3679` - // Minimum execution time: 39_231_000 picoseconds. - Weight::from_parts(39_935_000, 0) + // Minimum execution time: 23_000_000 picoseconds. + Weight::from_parts(26_554_140, 0) .saturating_add(Weight::from_parts(0, 3679)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -67,17 +65,19 @@ impl pallet_programs::WeightInfo for WeightInfo { /// Storage: `Programs::OwnedPrograms` (r:1 w:1) /// Proof: `Programs::OwnedPrograms` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `p` is `[0, 250]`. - fn remove_program(p: u32, ) -> Weight { + /// The range of component `o` is `[0, 10]`. + fn remove_program(p: u32, o: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `354 + p * (32 ±0)` - // Estimated: `3823 + p * (32 ±0)` - // Minimum execution time: 38_105_000 picoseconds. - Weight::from_parts(40_094_638, 0) - .saturating_add(Weight::from_parts(0, 3823)) - // Standard Error: 1_384 - .saturating_add(Weight::from_parts(149_685, 0).saturating_mul(p.into())) + // Measured: `353 + o * (1 ±0) + p * (32 ±0)` + // Estimated: `3842 + o * (1 ±0) + p * (32 ±0)` + // Minimum execution time: 22_000_000 picoseconds. + Weight::from_parts(28_023_735, 0) + .saturating_add(Weight::from_parts(0, 3842)) + // Standard Error: 11_641 + .saturating_add(Weight::from_parts(103_353, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) .saturating_add(Weight::from_parts(0, 32).saturating_mul(p.into())) } -} \ No newline at end of file +}