Skip to content

Commit

Permalink
Implement sign and signature verification on ProofOfAttendance (#366)
Browse files Browse the repository at this point in the history
* [primitives/ceremonies] implement convenience methods on `ProofOfAttendance`

* [primitives/ceremonies] remove obsolete hash function on proof of attendance

* [ceremonies] replace pallet method `verify_attendee_signature` with the proof of attendance's method.

* [primitives/ceremonies] pass the attendee as borrow for the proof of attendance signed constructor

* [ceremonies] use the new proof of attendance constructor in the tests

* [primitives/ceremonies] fix clippy

* fmt

---------

Co-authored-by: brenzi <[email protected]>
Co-authored-by: Alain Brenzikofer <[email protected]>
  • Loading branch information
3 people authored Feb 20, 2024
1 parent ae8647d commit ad8cc43
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 35 deletions.
17 changes: 2 additions & 15 deletions ceremonies/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,8 @@ pub mod pallet {
) == Reputation::VerifiedUnlinked,
Error::<T>::AttendanceUnverifiedOrAlreadyUsed
);
if Self::verify_attendee_signature(p.clone()).is_err() {
return Err(<Error<T>>::BadProofOfAttendanceSignature.into());
};

ensure!(p.verify_signature(), Error::<T>::BadProofOfAttendanceSignature);

// this reputation must now be burned so it can not be used again
<ParticipantReputation<T>>::insert(
Expand Down Expand Up @@ -1717,18 +1716,6 @@ impl<T: Config> Pallet<T> {
Ok(result)
}

fn verify_attendee_signature(
proof: ProofOfAttendance<T::Signature, T::AccountId>,
) -> DispatchResult {
match proof.attendee_signature.verify(
&(proof.prover_public, proof.ceremony_index).encode()[..],
&proof.attendee_public,
) {
true => Ok(()),
false => Err(<Error<T>>::BadAttendeeSignature.into()),
}
}

pub fn get_meetup_location(
cc: CommunityCeremony,
meetup_idx: MeetupIndexType,
Expand Down
9 changes: 1 addition & 8 deletions ceremonies/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,7 @@ fn prove_attendance(
cindex: CeremonyIndexType,
attendee: &sr25519::Pair,
) -> TestProofOfAttendance {
let msg = (prover.clone(), cindex);
ProofOfAttendance {
prover_public: prover,
community_identifier: cid,
ceremony_index: cindex,
attendee_public: account_id(attendee),
attendee_signature: Signature::from(attendee.sign(&msg.encode())),
}
TestProofOfAttendance::signed(prover, cid, cindex, attendee)
}

/// Wrapper for EncointerCeremonies::register_participant that reduces boilerplate code.
Expand Down
59 changes: 47 additions & 12 deletions primitives/src/ceremonies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use crate::communities::{CommunityIdentifier, Location};

use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::{RuntimeDebug, H256};
use sp_runtime::traits::{BlakeTwo256, Hash, IdentifyAccount, Verify};
use sp_core::{Pair, RuntimeDebug};
use sp_runtime::traits::{IdentifyAccount, Verify};

pub use crate::scheduler::CeremonyIndexType;

Expand Down Expand Up @@ -213,6 +213,8 @@ impl CommunityReputation {
}
}

pub type AccountIdFor<Signature> = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;

#[derive(
Encode, Decode, Copy, Clone, PartialEq, Eq, Default, RuntimeDebug, TypeInfo, MaxEncodedLen,
)]
Expand All @@ -226,17 +228,36 @@ pub struct ProofOfAttendance<Signature, AccountId> {
pub attendee_signature: Signature,
}

impl<Signature, AccountId: Clone + Encode> ProofOfAttendance<Signature, AccountId> {
/// get the hash of the proof without the attendee signature,
/// as the signature is non-deterministic.
pub fn hash(&self) -> H256 {
(
self.prover_public.clone(),
self.ceremony_index,
self.community_identifier,
self.attendee_public.clone(),
impl<Signature: Verify> ProofOfAttendance<Signature, AccountIdFor<Signature>>
where
AccountIdFor<Signature>: Clone + Encode,
{
pub fn verify_signature(&self) -> bool {
self.attendee_signature.verify(
&(self.prover_public.clone(), self.ceremony_index).encode()[..],
&self.attendee_public,
)
.using_encoded(BlakeTwo256::hash)
}

pub fn signed<Signer>(
prover_public: AccountIdFor<Signature>,
cid: CommunityIdentifier,
cindex: CeremonyIndexType,
attendee: &Signer,
) -> Self
where
Signer: Pair,
Signature: From<Signer::Signature>,
AccountIdFor<Signature>: From<Signer::Public>,
{
let msg = (prover_public.clone(), cindex);
ProofOfAttendance {
prover_public,
community_identifier: cid,
ceremony_index: cindex,
attendee_public: attendee.public().into(),
attendee_signature: attendee.sign(&msg.encode()).into(),
}
}
}

Expand Down Expand Up @@ -377,4 +398,18 @@ mod tests {

assert!(claim.verify_signature())
}

#[test]
fn proof_of_attendance_signing_works() {
let alice = AccountKeyring::Alice.pair();

let proof = ProofOfAttendance::<Signature, _>::signed(
alice.public().into(),
Default::default(),
1,
&alice,
);

assert!(proof.verify_signature())
}
}

0 comments on commit ad8cc43

Please sign in to comment.