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

Implement sign and signature verification on ProofOfAttendance #366

Merged
merged 8 commits into from
Feb 20, 2024
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 {
Comment on lines -229 to -232
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this, as it was unused.

(
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())
}
}
Loading