diff --git a/README.md b/README.md index d3ee86b..6120999 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ This will compile your program and put the `.wasm` binary file in `./binary-dir` Before running the runtime tests, you need to build the `template-barebones`, `infinite-loop` and `example-custom-hash` components. To do this, execute: ```bash -cargo component build --release -p template-barebones -p infinite-loop -p example-custom-hash --target wasm32-unknown-unknown` +cargo component build --release -p template-barebones -p infinite-loop -p example-custom-hash --target wasm32-unknown-unknown ``` This will create the components in `target/wasm32-unknown-unknown/release/`. diff --git a/examples/barebones-with-auxilary/src/lib.rs b/examples/barebones-with-auxilary/src/lib.rs index 2ef7b42..d2e159d 100644 --- a/examples/barebones-with-auxilary/src/lib.rs +++ b/examples/barebones-with-auxilary/src/lib.rs @@ -16,7 +16,11 @@ pub struct BarebonesWithAuxilary; impl Program for BarebonesWithAuxilary { /// This is the only function required by the program runtime. `signature_request` includes the message to be /// signed, eg. RLP-serialized Ethereum transaction request, raw x86_64 executable, etc. - fn evaluate(signature_request: SignatureRequest, _config: Option>) -> Result<(), Error> { + fn evaluate( + signature_request: SignatureRequest, + _config: Option>, + _oracle_data: Option>, + ) -> Result<(), Error> { let SignatureRequest { message, auxilary_data, @@ -57,7 +61,7 @@ mod tests { auxilary_data: Some(vec![0x00]), }; - assert!(BarebonesWithAuxilary::evaluate(signature_request, None).is_ok()); + assert!(BarebonesWithAuxilary::evaluate(signature_request, None, None).is_ok()); } /// Note, the program is written s.t. if `message` is less than 10 bytes, the program will error. @@ -69,7 +73,7 @@ mod tests { auxilary_data: Some(vec![0x00]), }; - assert!(BarebonesWithAuxilary::evaluate(signature_request, None).is_err()); + assert!(BarebonesWithAuxilary::evaluate(signature_request, None, None).is_err()); } /// Note, the program is written s.t. if `auxilary_data` is `None`, the program will error. @@ -81,6 +85,6 @@ mod tests { auxilary_data: None, }; - assert!(BarebonesWithAuxilary::evaluate(signature_request, None).is_err()); + assert!(BarebonesWithAuxilary::evaluate(signature_request, None, None).is_err()); } } diff --git a/examples/barebones/src/lib.rs b/examples/barebones/src/lib.rs index dad3d70..7496208 100644 --- a/examples/barebones/src/lib.rs +++ b/examples/barebones/src/lib.rs @@ -16,7 +16,11 @@ pub struct BarebonesProgram; impl Program for BarebonesProgram { /// This is the only function required by the program runtime. `message` is the preimage of the curve element to be /// signed, eg. RLP-serialized Ethereum transaction request, raw x86_64 executable, etc. - fn evaluate(signature_request: SignatureRequest, _config: Option>) -> Result<(), Error> { + fn evaluate( + signature_request: SignatureRequest, + _config: Option>, + _oracle_data: Option>, + ) -> Result<(), Error> { let message: Vec = signature_request.message; // our program just checks that the length of the message is greater than 10 @@ -49,7 +53,7 @@ mod tests { auxilary_data: None, }; - assert!(BarebonesProgram::evaluate(signature_request, None).is_ok()); + assert!(BarebonesProgram::evaluate(signature_request, None, None).is_ok()); } #[test] @@ -60,6 +64,6 @@ mod tests { auxilary_data: None, }; - assert!(BarebonesProgram::evaluate(signature_request, None).is_err()); + assert!(BarebonesProgram::evaluate(signature_request, None, None).is_err()); } } diff --git a/examples/basic-transaction/src/lib.rs b/examples/basic-transaction/src/lib.rs index 0896a56..f47b717 100644 --- a/examples/basic-transaction/src/lib.rs +++ b/examples/basic-transaction/src/lib.rs @@ -7,10 +7,14 @@ use entropy_programs::{ programs::acl::*, }; -use alloc::{vec::Vec, string::{String, ToString}, format}; +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; +use serde::{Deserialize, Serialize}; use serde_json; -use serde::{Serialize, Deserialize}; pub struct BasicTransaction; @@ -26,22 +30,29 @@ impl Program for BasicTransaction { /// This is the function that the programs engine will runtime esecute. signature_request is the preimage of the curve element to be /// signed, eg. RLP-serialized Ethereum transaction request, raw x86_64 executable, etc. // #[no_mangle] - fn evaluate(signature_request: SignatureRequest, config: Option>) -> Result<(), CoreError> { + fn evaluate( + signature_request: SignatureRequest, + config: Option>, + _oracle_data: Option>, + ) -> Result<(), CoreError> { // parse the raw tx into some type supported by the Acl check - let parsed_tx = - ::TransactionRequest::try_parse(signature_request.message.as_slice())?; + let parsed_tx = ::TransactionRequest::try_parse( + signature_request.message.as_slice(), + )?; // construct a allowlist ACL from the config let typed_config = serde_json::from_slice::( - config.ok_or(CoreError::Evaluation("No config provided.".to_string()))?.as_slice() - ).map_err(|e| CoreError::Evaluation(format!("Failed to parse config: {}", e)))?; - - let addresses: Vec<::AddressRaw> = - typed_config - .allowlisted_addresses - .iter() - .map(|a| hex::decode(a).unwrap().try_into().unwrap()) - .collect(); + config + .ok_or(CoreError::Evaluation("No config provided.".to_string()))? + .as_slice(), + ) + .map_err(|e| CoreError::Evaluation(format!("Failed to parse config: {}", e)))?; + + let addresses: Vec<::AddressRaw> = typed_config + .allowlisted_addresses + .iter() + .map(|a| hex::decode(a).unwrap().try_into().unwrap()) + .collect(); let allowlisted_acl = Acl::<::AddressRaw> { addresses, @@ -75,17 +86,18 @@ mod tests { "772b9a9e8aa1c9db861c6611a82d251db4fac990" ] } - "#.as_bytes(); + "# + .as_bytes(); #[test] fn test_evaluate() { let signature_request = SignatureRequest { // `data` is an RLP serialized ETH transaction with the recipient set to `0x772b9a9e8aa1c9db861c6611a82d251db4fac990` message: EVM_TX_WITH_ALLOWLISTED_RECIPIENT.to_vec(), - auxilary_data: None + auxilary_data: None, }; - assert!(BasicTransaction::evaluate(signature_request, Some(CONFIG.to_vec())).is_ok()); + assert!(BasicTransaction::evaluate(signature_request, Some(CONFIG.to_vec()), None).is_ok()); } #[test] @@ -93,9 +105,11 @@ mod tests { let signature_request = SignatureRequest { // `data` is the same as previous test, but recipient address ends in `1` instead of `0`, so it should fail message: EVM_TX_WITH_NONALLOWLISTED_RECIPIENT.to_vec(), - auxilary_data: None + auxilary_data: None, }; - assert!(BasicTransaction::evaluate(signature_request, Some(CONFIG.to_vec())).is_err()); + assert!( + BasicTransaction::evaluate(signature_request, Some(CONFIG.to_vec()), None).is_err() + ); } } diff --git a/examples/custom-hash/src/lib.rs b/examples/custom-hash/src/lib.rs index 9841dc7..1e1d7e2 100644 --- a/examples/custom-hash/src/lib.rs +++ b/examples/custom-hash/src/lib.rs @@ -16,7 +16,11 @@ register_custom_getrandom!(always_fail); pub struct CustomHashExample; impl Program for CustomHashExample { - fn evaluate(signature_request: SignatureRequest, _config: Option>) -> Result<(), Error> { + fn evaluate( + signature_request: SignatureRequest, + _config: Option>, + _oracle_data: Option>, + ) -> Result<(), Error> { if signature_request.message.len() < 1 { return Err(Error::Evaluation( "You need to give me SOME data to sign!".to_string(), diff --git a/examples/device-key-proxy/src/lib.rs b/examples/device-key-proxy/src/lib.rs index 9a92de5..a3d1062 100644 --- a/examples/device-key-proxy/src/lib.rs +++ b/examples/device-key-proxy/src/lib.rs @@ -250,6 +250,7 @@ impl Program for DeviceKeyProxy { fn evaluate( signature_request: SignatureRequest, raw_config: Option>, + _oracle_data: Option>, ) -> Result<(), Error> { let config_json = serde_json::from_slice::( raw_config diff --git a/examples/device-key-proxy/src/tests.rs b/examples/device-key-proxy/src/tests.rs index 4caf357..665fdf0 100644 --- a/examples/device-key-proxy/src/tests.rs +++ b/examples/device-key-proxy/src/tests.rs @@ -62,10 +62,12 @@ fn test_ok_for_only_device_key_signatures() { let config_bytes = serde_json::to_vec(&json_config).unwrap(); // positive for edcsa - assert!( - DeviceKeyProxy::evaluate(request_from_device_key.clone(), Some(config_bytes.clone())) - .is_ok() - ); + assert!(DeviceKeyProxy::evaluate( + request_from_device_key.clone(), + Some(config_bytes.clone()), + None + ) + .is_ok()); // positive for sr25519 let context = signing_context(b""); @@ -83,10 +85,12 @@ fn test_ok_for_only_device_key_signatures() { .unwrap() .into_bytes(), ); - assert!( - DeviceKeyProxy::evaluate(request_from_device_key.clone(), Some(config_bytes.clone())) - .is_ok() - ); + assert!(DeviceKeyProxy::evaluate( + request_from_device_key.clone(), + Some(config_bytes.clone()), + None + ) + .is_ok()); // positive for ed25519 let ed25519_device_key_signature: Ed25519Signature = device_keys.ed25519_keys[0].sign(message.as_bytes()); @@ -101,7 +105,7 @@ fn test_ok_for_only_device_key_signatures() { .unwrap() .into_bytes(), ); - DeviceKeyProxy::evaluate(request_from_device_key, Some(config_bytes.clone())).unwrap(); + DeviceKeyProxy::evaluate(request_from_device_key, Some(config_bytes.clone()), None).unwrap(); } #[test] @@ -159,9 +163,13 @@ fn test_fail_bad_signatures() { let config_bytes = serde_json::to_vec(&json_config).unwrap(); // fail for edcsa assert_eq!( - DeviceKeyProxy::evaluate(request_from_device_key.clone(), Some(config_bytes.clone())) - .unwrap_err() - .to_string(), + DeviceKeyProxy::evaluate( + request_from_device_key.clone(), + Some(config_bytes.clone()), + None + ) + .unwrap_err() + .to_string(), "Error::InvalidSignatureRequest(\"Unable to verify ecdsa signature\")" ); let sr25519_non_device_key_signature: Sr25519Signature = @@ -179,9 +187,13 @@ fn test_fail_bad_signatures() { .into_bytes(), ); assert_eq!( - DeviceKeyProxy::evaluate(request_from_device_key.clone(), Some(config_bytes.clone())) - .unwrap_err() - .to_string(), + DeviceKeyProxy::evaluate( + request_from_device_key.clone(), + Some(config_bytes.clone()), + None + ) + .unwrap_err() + .to_string(), "Error::InvalidSignatureRequest(\"Unable to verify sr25519 signature\")" ); // fail for ed25519 @@ -199,9 +211,13 @@ fn test_fail_bad_signatures() { .into_bytes(), ); assert_eq!( - DeviceKeyProxy::evaluate(request_from_device_key.clone(), Some(config_bytes.clone())) - .unwrap_err() - .to_string(), + DeviceKeyProxy::evaluate( + request_from_device_key.clone(), + Some(config_bytes.clone()), + None + ) + .unwrap_err() + .to_string(), "Error::InvalidSignatureRequest(\"Unable to verify ed25519 signature\")" ); } @@ -258,7 +274,8 @@ fn test_fails_pub_key_not_found() { assert_eq!( DeviceKeyProxy::evaluate( request_from_non_device_key.clone(), - Some(config_bytes.clone()) + Some(config_bytes.clone()), + None ) .unwrap_err() .to_string(), @@ -284,7 +301,8 @@ fn test_fails_pub_key_not_found() { assert_eq!( DeviceKeyProxy::evaluate( request_from_non_device_key.clone(), - Some(config_bytes.clone()) + Some(config_bytes.clone()), + None ) .unwrap_err() .to_string(), @@ -306,7 +324,7 @@ fn test_fails_pub_key_not_found() { .into_bytes(), ); assert_eq!( - DeviceKeyProxy::evaluate(request_from_non_device_key, Some(config_bytes)) + DeviceKeyProxy::evaluate(request_from_non_device_key, Some(config_bytes), None) .unwrap_err() .to_string(), "Error::InvalidSignatureRequest(\"Ed25519 Public key not in config\")" @@ -347,7 +365,8 @@ fn test_fails_with_no_aux_or_config() { assert_eq!( DeviceKeyProxy::evaluate( request_from_device_key_no_aux.clone(), - Some(config_bytes.clone()) + Some(config_bytes.clone()), + None ) .unwrap_err() .to_string(), @@ -378,7 +397,7 @@ fn test_fails_with_no_aux_or_config() { ), }; assert_eq!( - DeviceKeyProxy::evaluate(request_from_device_key.clone(), None) + DeviceKeyProxy::evaluate(request_from_device_key.clone(), None, None) .unwrap_err() .to_string(), "Error::Evaluation(\"No config provided.\")" @@ -391,7 +410,7 @@ fn test_fails_with_no_aux_or_config() { .into_bytes(), ); assert_eq!( - DeviceKeyProxy::evaluate(request_from_device_key, Some(config_bytes.clone())) + DeviceKeyProxy::evaluate(request_from_device_key, Some(config_bytes.clone()), None) .unwrap_err() .to_string(), "Error::InvalidSignatureRequest(\"Invalid public key type\")" diff --git a/examples/infinite-loop/src/lib.rs b/examples/infinite-loop/src/lib.rs index b53dee8..78aa951 100644 --- a/examples/infinite-loop/src/lib.rs +++ b/examples/infinite-loop/src/lib.rs @@ -12,7 +12,11 @@ pub struct InfiniteLoop; impl Program for InfiniteLoop { /// This is the only function required by the program runtime. `message` is the preimage of the curve element to be /// signed, eg. RLP-serialized Ethereum transaction request, raw x86_64 executable, etc. - fn evaluate(_signature_request: SignatureRequest, _config: Option>) -> Result<(), Error> { + fn evaluate( + _signature_request: SignatureRequest, + _config: Option>, + _oracle_data: Option>, + ) -> Result<(), Error> { loop {} #[allow(unreachable_code)] Ok(()) diff --git a/examples/private-acl/src/lib.rs b/examples/private-acl/src/lib.rs index 6aab2bc..36a2c8a 100644 --- a/examples/private-acl/src/lib.rs +++ b/examples/private-acl/src/lib.rs @@ -24,7 +24,11 @@ register_custom_getrandom!(always_fail); impl Program for PrivateTransactionAcl { /// Allow any address given in the pre-defined list (addresses.txt) // #[no_mangle] - fn evaluate(signature_request: SignatureRequest, _config: Option>) -> Result<(), CoreError> { + fn evaluate( + signature_request: SignatureRequest, + _config: Option>, + _oracle_data: Option>, + ) -> Result<(), CoreError> { // parse the raw tx into some type let parsed_tx = ::TransactionRequest::try_parse( signature_request.message.as_slice(), @@ -72,7 +76,7 @@ mod tests { auxilary_data: None, }; - assert!(PrivateTransactionAcl::evaluate(signature_request, None).is_ok()); + assert!(PrivateTransactionAcl::evaluate(signature_request, None, None).is_ok()); } #[test] @@ -83,6 +87,6 @@ mod tests { auxilary_data: None, }; - assert!(PrivateTransactionAcl::evaluate(signature_request, None).is_err()); + assert!(PrivateTransactionAcl::evaluate(signature_request, None, None).is_err()); } } diff --git a/examples/risczero-zkvm-verification/src/lib.rs b/examples/risczero-zkvm-verification/src/lib.rs index 0dea8c2..5c805e8 100644 --- a/examples/risczero-zkvm-verification/src/lib.rs +++ b/examples/risczero-zkvm-verification/src/lib.rs @@ -17,7 +17,7 @@ register_custom_getrandom!(always_fail); pub struct ZkVmVerificationProgram; impl Program for ZkVmVerificationProgram { - fn evaluate(signature_request: SignatureRequest, _config: Option>) -> Result<(), Error> { + fn evaluate(signature_request: SignatureRequest, _config: Option>, _oracle_data: Option>) -> Result<(), Error> { let image_id: [u32; 8] = bincode::deserialize(&signature_request.message) .map_err(|_| Error::InvalidSignatureRequest("Could not parse image_id".to_string()))?; @@ -92,7 +92,7 @@ mod tests { auxilary_data: Some(bincode::serialize(&read_test_receipt()).unwrap()), }; - assert!(ZkVmVerificationProgram::evaluate(signature_request, None).is_ok()); + assert!(ZkVmVerificationProgram::evaluate(signature_request, None, None).is_ok()); } #[test] @@ -102,7 +102,7 @@ mod tests { auxilary_data: Some(bincode::serialize(&read_test_receipt()).unwrap()), }; - assert!(ZkVmVerificationProgram::evaluate(signature_request, None).is_err()); + assert!(ZkVmVerificationProgram::evaluate(signature_request, None, None).is_err()); } // Test helper functions diff --git a/examples/siwe/src/lib.rs b/examples/siwe/src/lib.rs index 746ef37..1e591e4 100644 --- a/examples/siwe/src/lib.rs +++ b/examples/siwe/src/lib.rs @@ -24,7 +24,11 @@ const ALLOWED_DOMAIN: &str = "localhost"; pub struct Siwe; impl Program for Siwe { - fn evaluate(signature_request: SignatureRequest, _config: Option>) -> Result<(), Error> { + fn evaluate( + signature_request: SignatureRequest, + _config: Option>, + _oracle_data: Option>, + ) -> Result<(), Error> { let string_message = String::from_utf8(signature_request.message) .map_err(|err| Error::Evaluation(err.to_string()))?; let siwe_message = string_message @@ -71,7 +75,7 @@ Issued At: 2022-01-28T23:28:16.013Z" auxilary_data: None, }; - assert!(Siwe::evaluate(signature_request, None).is_ok()); + assert!(Siwe::evaluate(signature_request, None, None).is_ok()); } #[test] @@ -92,7 +96,7 @@ Issued At: 2022-01-28T23:28:16.013Z" auxilary_data: None, }; - assert!(Siwe::evaluate(signature_request, None).is_err()); + assert!(Siwe::evaluate(signature_request, None, None).is_err()); } #[test] @@ -113,6 +117,6 @@ Issued At: 2022-01-28T23:28:16.013Z" auxilary_data: None, }; - assert!(Siwe::evaluate(signature_request, None).is_err()); + assert!(Siwe::evaluate(signature_request, None, None).is_err()); } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 4410034..e1d3194 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -41,9 +41,7 @@ pub struct Config { impl Default for Config { fn default() -> Self { - Self { - fuel: 10_000, - } + Self { fuel: 10_000 } } } @@ -86,7 +84,8 @@ impl Runtime { &mut self, program: &[u8], signature_request: &SignatureRequest, - config: Option<&[u8]> + config: Option<&[u8]>, + oracle_data: Option<&[u8]>, ) -> Result<(), RuntimeError> { if program.len() == 0 { return Err(RuntimeError::EmptyBytecode); @@ -98,13 +97,17 @@ impl Runtime { .map_err(|_| RuntimeError::InvalidBytecode)?; bindings - .call_evaluate(&mut self.store, signature_request, config) + .call_evaluate(&mut self.store, signature_request, config, oracle_data) .map_err(|_| RuntimeError::OutOfFuel)? .map_err(RuntimeError::Runtime) } /// Compute the `custom-hash` of a `message` from the program. - pub fn custom_hash(&mut self, program: &[u8], message: &[u8]) -> Result<[u8; 32], RuntimeError> { + pub fn custom_hash( + &mut self, + program: &[u8], + message: &[u8], + ) -> Result<[u8; 32], RuntimeError> { if program.len() == 0 { return Err(RuntimeError::EmptyBytecode); } @@ -118,7 +121,12 @@ impl Runtime { .call_custom_hash(&mut self.store, message) .unwrap().ok_or(RuntimeError::Runtime(ProgramError::InvalidSignatureRequest("`custom-hash` returns `None`. Implement the hash function in your program, or select a predefined `hash` in your signature request.".to_string())))?; if hash_as_vec.len() != 32 { - return Err(RuntimeError::Runtime(ProgramError::InvalidSignatureRequest(format!("`custom-hash` must returns a Vec of length 32, not {}.", hash_as_vec.len())))); + return Err(RuntimeError::Runtime( + ProgramError::InvalidSignatureRequest(format!( + "`custom-hash` must returns a Vec of length 32, not {}.", + hash_as_vec.len() + )), + )); } let mut hash = [0u8; 32]; diff --git a/runtime/tests/runtime.rs b/runtime/tests/runtime.rs index 788d753..4052fd8 100644 --- a/runtime/tests/runtime.rs +++ b/runtime/tests/runtime.rs @@ -21,7 +21,7 @@ fn test_barebones_component() { auxilary_data: None, }; - let res = runtime.evaluate(BAREBONES_COMPONENT_WASM, &signature_request, None); + let res = runtime.evaluate(BAREBONES_COMPONENT_WASM, &signature_request, None, None); assert!(res.is_ok()); } @@ -36,7 +36,7 @@ fn test_barebones_component_fails_with_data_length_less_than_10() { auxilary_data: None, }; - let res = runtime.evaluate(BAREBONES_COMPONENT_WASM, &signature_request, None); + let res = runtime.evaluate(BAREBONES_COMPONENT_WASM, &signature_request, None, None); assert!(res.is_err()); } @@ -49,7 +49,7 @@ fn test_empty_bytecode_fails() { auxilary_data: None, }; - let res = runtime.evaluate(&[], &signature_request, None); + let res = runtime.evaluate(&[], &signature_request, None, None); assert_eq!(res.unwrap_err().to_string(), "Bytecode length is zero"); } @@ -62,7 +62,7 @@ fn test_infinite_loop() { auxilary_data: None, }; - let res = runtime.evaluate(INFINITE_LOOP_WASM, &signature_request, None); + let res = runtime.evaluate(INFINITE_LOOP_WASM, &signature_request, None, None); assert_eq!(res.unwrap_err().to_string(), "Out of fuel"); } diff --git a/templates/basic-template/src/tests.rs b/templates/basic-template/src/tests.rs index 86d3ae0..7c871a1 100644 --- a/templates/basic-template/src/tests.rs +++ b/templates/basic-template/src/tests.rs @@ -7,7 +7,7 @@ fn test_should_sign() { auxilary_data: None, }; - assert!({{project-name | upper_camel_case}}::evaluate(signature_request, None).is_ok()); + assert!({{project-name | upper_camel_case}}::evaluate(signature_request, None, None).is_ok()); } #[test] @@ -17,5 +17,5 @@ fn test_should_fail() { auxilary_data: None, }; - assert!({{project-name | upper_camel_case}}::evaluate(signature_request, None).is_err()); + assert!({{project-name | upper_camel_case}}::evaluate(signature_request, None, None).is_err()); } \ No newline at end of file diff --git a/wit/application.wit b/wit/application.wit index 6320ee5..bfdf9ec 100644 --- a/wit/application.wit +++ b/wit/application.wit @@ -8,7 +8,7 @@ world program { evaluation(string) } /// Evaluates the program given the user's signature request and the program's configuration. - export evaluate: func(signature-request: signature-request, config: option>) -> result<_, error> + export evaluate: func(signature-request: signature-request, config: option>, oracle-data: option>) -> result<_, error> /// Programs that use custom hash functions can a custom 32-byte curve point to be signed. export custom-hash: func(data: list) -> option>