From 58cb83cff46bcd12a6c2a1b869a586f9a3f5e4f0 Mon Sep 17 00:00:00 2001 From: JesseAbram <33698952+JesseAbram@users.noreply.github.com> Date: Fri, 5 Jan 2024 22:23:28 -0800 Subject: [PATCH] Additive aux data (#577) * addative aux data * changelog * fix wasm test * refactor * error if aux data is incorrect length * fix test --- CHANGELOG.md | 3 +- crates/testing-utils/src/test_client/mod.rs | 2 +- .../src/user/api.rs | 33 +++++++++++-------- .../src/user/errors.rs | 2 ++ .../src/user/tests.rs | 25 +++++++++++--- .../tests/protocol_wasm.rs | 5 ++- 6 files changed, 49 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index baa888857..dfcd18cf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ At the moment this project **does not** adhere to - Wasm API to entropy-protocol uses camelCase function names ([#566](https://github.com/entropyxyz/entropy-core/pull/566)) - Wasm API to functions formerly in the x25515chacha20poly1305 repo also now have camelCase function names ([#563](https://github.com/entropyxyz/entropy-core/pull/563)) - Register and change program pointer interface changed to accept a vecotor of programs. As well pass an index for which containts the hashing code if it custom hashing ([#568](https://github.com/entropyxyz/entropy-core/pull/568)) - +- If a user is sending additive data through it now needs to be in a vector and the index needs to match up with where the program pointer is in the program pointer vector. ([#577](https://github.com/entropyxyz/entropy-core/pull/577)) ### Added - Test CLI which calls the same code as in integration tests ([#417](https://github.com/entropyxyz/entropy-core/pull/417)) - Include contents of x25515chacha20poly1305 repo in entropy-protocol ([#563](https://github.com/entropyxyz/entropy-core/pull/563)) @@ -34,6 +34,7 @@ At the moment this project **does not** adhere to - Change bip39 implementation ([#562](https://github.com/entropyxyz/entropy-core/pull/562)) - Additive programs ([#568](https://github.com/entropyxyz/entropy-core/pull/568)) - Additional `hash` field in `/sign_tx` JSON body indicates which hashing algorithm to use for signing ([#553](https://github.com/entropyxyz/entropy-core/pull/553)) +- Additive aux data ([#577](https://github.com/entropyxyz/entropy-core/pull/577)) ### Added diff --git a/crates/testing-utils/src/test_client/mod.rs b/crates/testing-utils/src/test_client/mod.rs index 5550d6ab8..c661fa67d 100644 --- a/crates/testing-utils/src/test_client/mod.rs +++ b/crates/testing-utils/src/test_client/mod.rs @@ -148,7 +148,7 @@ pub async fn sign( let signature_request = UserSignatureRequest { message: hex::encode(message), - auxilary_data: auxilary_data.map(hex::encode), + auxilary_data: Some(vec![auxilary_data.map(hex::encode)]), validators_info: validators_info.clone(), timestamp: SystemTime::now(), hash: HashingAlgorithm::Keccak, diff --git a/crates/threshold-signature-server/src/user/api.rs b/crates/threshold-signature-server/src/user/api.rs index 1267bc04a..bccc83cbe 100644 --- a/crates/threshold-signature-server/src/user/api.rs +++ b/crates/threshold-signature-server/src/user/api.rs @@ -85,7 +85,7 @@ pub struct UserSignatureRequest { /// Hex-encoded raw data to be signed (eg. hex-encoded RLP-serialized Ethereum transaction) pub message: String, /// Hex-encoded auxilary data for program evaluation, will not be signed (eg. zero-knowledge proof, serialized struct, etc) - pub auxilary_data: Option, + pub auxilary_data: Option>>, /// Information from the validators in signing party pub validators_info: Vec, /// When the message was created and signed @@ -145,29 +145,34 @@ pub async fn sign_tx( check_stale(user_sig_req.timestamp)?; let message = hex::decode(&user_sig_req.message)?; - let auxilary_data = user_sig_req.auxilary_data.as_ref().map(hex::decode).transpose()?; let mut runtime = Runtime::new(); - let signature_request = SignatureRequest { message, auxilary_data }; if user_details.program_pointers.0.is_empty() { return Err(UserErr::NoProgramPointerDefined()); } + // handle aux data padding, if it is not explicit by client for ease send through None, error if incorrect length + let auxilary_data_vec; + if let Some(auxilary_data) = user_sig_req.clone().auxilary_data { + if auxilary_data.len() < user_details.program_pointers.0.len() { + return Err(UserErr::MismatchAuxData); + } else { + auxilary_data_vec = auxilary_data; + } + } else { + auxilary_data_vec = vec![None; user_details.program_pointers.0.len()]; + } - for program_pointer in &user_details.program_pointers.0 { + for (i, program_pointer) in user_details.program_pointers.0.iter().enumerate() { let program = get_program(&api, &rpc, program_pointer).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, &signature_request)?; } // We decided to do Keccak for subgroup selection for frontend compatability - let message_hash_keccak = compute_hash( - &api, - &rpc, - &HashingAlgorithm::Keccak, - &mut runtime, - &[], - signature_request.message.as_slice(), - ) - .await?; + let message_hash_keccak = + compute_hash(&api, &rpc, &HashingAlgorithm::Keccak, &mut runtime, &[], message.as_slice()) + .await?; let message_hash_keccak_hex = hex::encode(message_hash_keccak); let subgroup_signers = @@ -184,7 +189,7 @@ pub async fn sign_tx( &user_sig_req.hash, &mut runtime, &user_details.program_pointers.0, - signature_request.message.as_slice(), + message.as_slice(), ) .await?; let message_hash_hex = hex::encode(message_hash); diff --git a/crates/threshold-signature-server/src/user/errors.rs b/crates/threshold-signature-server/src/user/errors.rs index 71a93e11a..f350b94b9 100644 --- a/crates/threshold-signature-server/src/user/errors.rs +++ b/crates/threshold-signature-server/src/user/errors.rs @@ -133,6 +133,8 @@ pub enum UserErr { ProtocolExecution(#[from] ProtocolExecutionErr), #[error("Encryption or signing error: {0}")] Json(#[from] entropy_protocol::sign_and_encrypt::SignedMessageErr), + #[error("Auxilary data is mismatched")] + MismatchAuxData, } impl IntoResponse for UserErr { diff --git a/crates/threshold-signature-server/src/user/tests.rs b/crates/threshold-signature-server/src/user/tests.rs index 1ac33ac2c..e3733ab64 100644 --- a/crates/threshold-signature-server/src/user/tests.rs +++ b/crates/threshold-signature-server/src/user/tests.rs @@ -160,7 +160,10 @@ async fn test_sign_tx_no_chain() { let mut generic_msg = UserSignatureRequest { message: hex::encode(PREIMAGE_SHOULD_SUCCEED), - auxilary_data: Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + auxilary_data: Some(vec![ + Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + ]), validators_info, timestamp: SystemTime::now(), hash: HashingAlgorithm::Keccak, @@ -328,8 +331,23 @@ async fn test_sign_tx_no_chain() { ); } + // The test program is written to fail when `auxilary_data` is `None` but only on the second program + generic_msg.auxilary_data = Some(vec![Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED))]); + generic_msg.timestamp = SystemTime::now(); + + let test_user_failed_aux_data = + submit_transaction_requests(validator_ips_and_keys.clone(), generic_msg.clone(), one).await; + + for res in test_user_failed_aux_data { + assert_eq!(res.unwrap().text().await.unwrap(), "Auxilary data is mismatched"); + } + // program gets removed and errors remove_program(&entropy_api, &rpc, &two.pair(), program_hash).await; + generic_msg.auxilary_data = Some(vec![ + Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + ]); generic_msg.timestamp = SystemTime::now(); // test failing cases let test_program_pulled = @@ -456,7 +474,7 @@ async fn test_fail_signing_group() { let generic_msg = UserSignatureRequest { message: hex::encode(PREIMAGE_SHOULD_SUCCEED), - auxilary_data: Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + auxilary_data: Some(vec![Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED))]), validators_info, timestamp: SystemTime::now(), hash: HashingAlgorithm::Keccak, @@ -870,7 +888,7 @@ async fn test_sign_tx_user_participates() { let mut generic_msg = UserSignatureRequest { message: encoded_transaction_request.clone(), - auxilary_data: Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + auxilary_data: Some(vec![Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED))]), validators_info: validators_info.clone(), timestamp: SystemTime::now(), hash: HashingAlgorithm::Keccak, @@ -1240,7 +1258,6 @@ pub async fn verify_signature( let mut i = 0; for res in test_user_res { let mut res = res.unwrap(); - assert_eq!(res.status(), 200); let chunk = res.chunk().await.unwrap().unwrap(); let signing_result: Result<(String, Signature), String> = diff --git a/crates/threshold-signature-server/tests/protocol_wasm.rs b/crates/threshold-signature-server/tests/protocol_wasm.rs index 0720d15e2..4a1d1d515 100644 --- a/crates/threshold-signature-server/tests/protocol_wasm.rs +++ b/crates/threshold-signature-server/tests/protocol_wasm.rs @@ -107,7 +107,10 @@ async fn test_wasm_sign_tx_user_participates() { let mut generic_msg = UserSignatureRequest { message: encoded_transaction_request.clone(), - auxilary_data: Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + auxilary_data: Some(vec![ + Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + Some(hex::encode(AUXILARY_DATA_SHOULD_SUCCEED)), + ]), validators_info: validators_info.clone(), timestamp: SystemTime::now(), hash: HashingAlgorithm::Keccak,