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

Add example how to generate Ed25519 signature in the test case #357

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/signature-verifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ concordium-std = {path = "../../concordium-std"}

[dev-dependencies]
concordium-smart-contract-testing = { path = "../../contract-testing" }
ed25519-dalek = { version = "2.0", features = ["rand_core"] }
rand = "0.8.5"

[features]
default = ["std", "wee_alloc"]
Expand Down
89 changes: 84 additions & 5 deletions examples/signature-verifier/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ const ALICE_ADDR: Address = Address::Account(ALICE);
const SIGNER: Signer = Signer::with_one_key();

/// Tests that the signature verifier contract returns true when the signature
/// is valid.
/// is valid. The signature is generated outside this test case
/// (e.g. with https://cyphr.me/ed25519_tool/ed.html).
#[test]
fn test_signature_check() {
fn test_outside_signature_check() {
let mut chain = Chain::new();

// Create an account.
Expand Down Expand Up @@ -48,9 +49,9 @@ fn test_signature_check() {
.expect("Parameter has valid size."),
})
.expect("Call signature verifier contract with an invalid signature.");
// Check that it returns `false`.
// Check that the signature does NOT verify.
let rv: bool = update_invalid.parse_return_value().expect("Deserializing bool");
assert_eq!(rv, false);
assert!(!rv, "Signature verification should fail.");

// Construct a parameter with a valid signature.
let parameter_valid = VerificationParameter {
Expand All @@ -69,7 +70,85 @@ fn test_signature_check() {
.expect("Parameter has valid size."),
})
.expect("Call signature verifier contract with a valid signature.");
// Check that it returns `true`.
// Check that the signature verifies.
let rv: bool = update.parse_return_value().expect("Deserializing bool");
assert!(rv, "Signature checking failed.");
}

/// Tests that the signature verifier contract returns true when the signature
/// is valid. The signature is generated in the test case.
#[test]
fn test_inside_signature_check() {
let mut chain = Chain::new();

// Create an account.
chain.create_account(Account::new(ALICE, Amount::from_ccd(1000)));

// Load and deploy the module.
let module = module_load_v1("concordium-out/module.wasm.v1").expect("Module exists.");
let deployment = chain.module_deploy_v1(SIGNER, ALICE, module).expect("Module deploys.");

// Initialize the signature verifier contract.
let init = chain
.contract_init(SIGNER, ALICE, Energy::from(10_000), InitContractPayload {
amount: Amount::zero(),
mod_ref: deployment.module_reference,
init_name: OwnedContractName::new_unchecked("init_signature-verifier".to_string()),
param: OwnedParameter::empty(),
})
.expect("Initialize signature verifier contract");

use ed25519_dalek::{Signer, SigningKey};

let rng = &mut rand::thread_rng();

// Construct message, verifying_key, and signature.
let message: &[u8] = b"Concordium";
let signing_key = SigningKey::generate(rng);
let verifying_key = signing_key.verifying_key();
let signature = signing_key.sign(&message);

// Construct a parameter with an invalid signature.
let parameter_invalid = VerificationParameter {
public_key: PublicKeyEd25519(verifying_key.to_bytes()),
signature: SignatureEd25519(signature.to_bytes()),
message: b"wrong_message".to_vec(),
};

// Call the contract with the invalid signature.
let update_invalid = chain
.contract_update(SIGNER, ALICE, ALICE_ADDR, Energy::from(10_000), UpdateContractPayload {
amount: Amount::zero(),
address: init.contract_address,
receive_name: OwnedReceiveName::new_unchecked("signature-verifier.verify".to_string()),
message: OwnedParameter::from_serial(&parameter_invalid)
.expect("Parameter has valid size."),
})
.expect("Call signature verifier contract with an invalid signature.");

// Check that the signature does NOT verify.
let rv: bool = update_invalid.parse_return_value().expect("Deserializing bool");
assert!(!rv, "Signature verification should fail.");

// Construct a parameter with a valid signature.
let parameter_valid = VerificationParameter {
public_key: PublicKeyEd25519(verifying_key.to_bytes()),
signature: SignatureEd25519(signature.to_bytes()),
message: message.to_vec(),
};

// Call the contract with the valid signature.
let update = chain
.contract_update(SIGNER, ALICE, ALICE_ADDR, Energy::from(10_000), UpdateContractPayload {
amount: Amount::zero(),
address: init.contract_address,
receive_name: OwnedReceiveName::new_unchecked("signature-verifier.verify".to_string()),
message: OwnedParameter::from_serial(&parameter_valid)
.expect("Parameter has valid size."),
})
.expect("Call signature verifier contract with a valid signature.");

// Check that the signature verifies.
let rv: bool = update.parse_return_value().expect("Deserializing bool");
assert!(rv, "Signature checking failed.");
}
Loading