From 1db72e7a28b11c867c98569e95a1b990d48a80d0 Mon Sep 17 00:00:00 2001 From: JesseAbram <33698952+JesseAbram@users.noreply.github.com> Date: Wed, 15 Jan 2025 14:22:31 -0500 Subject: [PATCH] Allow different versions for programs (#1250) * Allow different versions for programs * docs * break up evaluation --- CHANGELOG.md | 1 + .../src/helpers/user.rs | 52 +++++++++++++++++-- .../src/user/api.rs | 30 +++++------ .../src/user/errors.rs | 2 + .../src/user/tests.rs | 4 +- 5 files changed, 67 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca4aa3c7e..a4cdfa80b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ runtime - Use context, not block number in TDX quote input data ([#1179](https://github.com/entropyxyz/entropy-core/pull/1179)) - Allow offchain worker requests to all TSS nodes in entropy-tss test environment ([#1147](https://github.com/entropyxyz/entropy-core/pull/1147)) - Extract PCK certificate chain from quotes ([#1209](https://github.com/entropyxyz/entropy-core/pull/1209)) +- Allow different versions for programs ([#1250](https://github.com/entropyxyz/entropy-core/pull/1250)) ### Fixed diff --git a/crates/threshold-signature-server/src/helpers/user.rs b/crates/threshold-signature-server/src/helpers/user.rs index 34aaeb41e..bfc49f0ba 100644 --- a/crates/threshold-signature-server/src/helpers/user.rs +++ b/crates/threshold-signature-server/src/helpers/user.rs @@ -16,7 +16,7 @@ //! Utilities relating to the user use std::time::Duration; -use entropy_programs_runtime::Runtime; +use entropy_programs_runtime::{Config as ProgramConfig, Runtime, SignatureRequest}; use entropy_protocol::{ execute_protocol::{execute_dkg, Channels}, KeyShareWithAuxInfo, Listener, SessionId, ValidatorInfo, @@ -32,7 +32,12 @@ use tokio::time::timeout; use x25519_dalek::StaticSecret; use crate::{ - chain_api::{entropy::runtime_types::pallet_registry::pallet::ProgramInstance, EntropyConfig}, + chain_api::{ + entropy::runtime_types::{ + pallet_programs::pallet::ProgramInfo, pallet_registry::pallet::ProgramInstance, + }, + EntropyConfig, + }, helpers::substrate::get_program, signing_client::{protocol_transport::open_protocol_connections, ListenerState}, user::errors::UserErr, @@ -114,7 +119,7 @@ pub async fn compute_hash( api: &OnlineClient, rpc: &LegacyRpcMethods, hashing_algorithm: &HashingAlgorithm, - runtime: &mut Runtime, + fuel: u64, programs_data: &[ProgramInstance], message: &[u8], ) -> Result<[u8; 32], UserErr> { @@ -154,8 +159,47 @@ pub async fn compute_hash( HashingAlgorithm::Blake2_256 => Ok(blake2_256(message)), HashingAlgorithm::Custom(i) => { let program_info = get_program(api, rpc, &programs_data[*i].program_pointer).await?; - runtime.custom_hash(program_info.bytecode.as_slice(), message).map_err(|e| e.into()) + evaluate_custom_hash(fuel, program_info, message) }, _ => Err(UserErr::UnknownHashingAlgorithm), } } + +/// Gets a runtime and evaluates a program for a specific runtime version. +pub fn evaluate_program( + fuel: u64, + program_info: ProgramInfo, + signature_request: SignatureRequest, + program_config: Vec, + oracle_data: Vec>, +) -> Result<(), UserErr> { + match program_info.version_number { + 0 => { + let mut runtime = Runtime::new(ProgramConfig { fuel }); + runtime + .evaluate( + &program_info.bytecode, + &signature_request, + Some(&program_config), + Some(&oracle_data), + ) + .map_err(|e| e.into()) + }, + _ => Err(UserErr::ProgramVersion), + } +} + +/// Gets a runtime and evaluates a custom hash for a specific runtime version. +pub fn evaluate_custom_hash( + fuel: u64, + program_info: ProgramInfo, + message: &[u8], +) -> Result<[u8; 32], UserErr> { + match program_info.version_number { + 0 => { + let mut runtime = Runtime::new(ProgramConfig { fuel }); + runtime.custom_hash(program_info.bytecode.as_slice(), message).map_err(|e| e.into()) + }, + _ => Err(UserErr::ProgramVersion), + } +} diff --git a/crates/threshold-signature-server/src/user/api.rs b/crates/threshold-signature-server/src/user/api.rs index c9397de91..4b29a9cac 100644 --- a/crates/threshold-signature-server/src/user/api.rs +++ b/crates/threshold-signature-server/src/user/api.rs @@ -24,7 +24,7 @@ use axum::{ use base64::prelude::{Engine, BASE64_STANDARD}; use entropy_client::substrate::get_registered_details; use entropy_kvdb::kv_manager::{helpers::serialize as key_serialize, KvManager}; -use entropy_programs_runtime::{Config as ProgramConfig, Runtime, SignatureRequest}; +use entropy_programs_runtime::SignatureRequest; use entropy_protocol::SigningSessionInfo; use entropy_shared::{HashingAlgorithm, OcwMessageDkg, NETWORK_PARENT_KEY}; use futures::{channel::mpsc, future::join_all, StreamExt}; @@ -50,7 +50,7 @@ use crate::{ get_oracle_data, get_program, get_signers_from_chain, get_validators_info, query_chain, submit_transaction, }, - user::{check_in_registration_group, compute_hash, do_dkg}, + user::{check_in_registration_group, compute_hash, do_dkg, evaluate_program}, validator::get_signer_and_x25519_secret, }, validation::{check_stale, EncryptedSignedMessage}, @@ -302,7 +302,7 @@ pub async fn sign_tx( .ok_or_else(|| UserErr::OptionUnwrapError("Error Getting Block Number".to_string()))? .number; - let (mut runtime, user_details, message) = pre_sign_checks( + let (fuel, user_details, message) = pre_sign_checks( &api, &rpc, relayer_sig_request.user_signature_request.clone(), @@ -315,7 +315,7 @@ pub async fn sign_tx( &api, &rpc, &relayer_sig_request.user_signature_request.hash, - &mut runtime, + fuel, &user_details.programs_data.0, message.as_slice(), ) @@ -649,7 +649,7 @@ pub async fn pre_sign_checks( user_sig_req: UserSignatureRequest, block_number: u32, string_verifying_key: String, -) -> Result<(Runtime, RegisteredInfo, Vec), UserErr> { +) -> Result<(u64, RegisteredInfo, Vec), UserErr> { check_stale(user_sig_req.block_number, block_number).await?; // Probably impossible but block signing from parent key anyways @@ -685,20 +685,20 @@ pub async fn pre_sign_checks( .await? .ok_or_else(|| UserErr::ChainFetch("Max instructions per program error"))?; - let mut runtime = Runtime::new(ProgramConfig { fuel }); - 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_pointers.0).await?; + let oracle_data = + get_oracle_data(api, rpc, program_info.oracle_data_pointers.0.clone()).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( - &program_info.bytecode, - &signature_request, - Some(&program_data.program_config), - Some(&oracle_data), - )?; + evaluate_program( + fuel, + program_info, + signature_request, + program_data.program_config.clone(), + oracle_data, + )? } - Ok((runtime, user_details, message)) + Ok((fuel, user_details, message)) } diff --git a/crates/threshold-signature-server/src/user/errors.rs b/crates/threshold-signature-server/src/user/errors.rs index c2f226c53..71bafd737 100644 --- a/crates/threshold-signature-server/src/user/errors.rs +++ b/crates/threshold-signature-server/src/user/errors.rs @@ -177,6 +177,8 @@ pub enum UserErr { TooFewSigners, #[error("Non signer sent from relayer")] IncorrectSigner, + #[error("Program Version not supported")] + ProgramVersion, } impl From for UserErr { diff --git a/crates/threshold-signature-server/src/user/tests.rs b/crates/threshold-signature-server/src/user/tests.rs index d2620049c..f74f24d25 100644 --- a/crates/threshold-signature-server/src/user/tests.rs +++ b/crates/threshold-signature-server/src/user/tests.rs @@ -21,7 +21,6 @@ use entropy_client::{ user::{get_all_signers_from_chain, UserSignatureRequest}, }; use entropy_kvdb::clean_tests; -use entropy_programs_runtime::Runtime; use entropy_protocol::{ decode_verifying_key, protocol_transport::{noise::noise_handshake_initiator, SubscribeMessage}, @@ -931,7 +930,6 @@ async fn test_compute_hash() { let api = get_api(&substrate_context.node_proc.ws_url).await.unwrap(); let rpc = get_rpc(&substrate_context.node_proc.ws_url).await.unwrap(); - let mut runtime = Runtime::default(); let program_hash = test_client::store_program( &api, &rpc, @@ -949,7 +947,7 @@ async fn test_compute_hash() { &api, &rpc, &HashingAlgorithm::Custom(0), - &mut runtime, + 10000000u64, &vec![ProgramInstance { program_pointer: program_hash, program_config: vec![] }], PREIMAGE_SHOULD_SUCCEED, )