QuorumValidator.cs
1 namespace GUNRPG.Security; 2 3 public sealed class QuorumValidator 4 { 5 public bool HasQuorum( 6 SignedRunValidation validation, 7 AuthoritySet authorities, 8 QuorumPolicy policy) 9 { 10 ArgumentNullException.ThrowIfNull(validation); 11 ArgumentNullException.ThrowIfNull(authorities); 12 ArgumentNullException.ThrowIfNull(policy); 13 14 var resultHash = validation.ComputeResultHash(); 15 var seenSigners = new HashSet<string>(StringComparer.Ordinal); 16 var validSignatures = 0; 17 18 foreach (var signature in validation.Signatures) 19 { 20 if (signature is null) 21 { 22 return false; 23 } 24 25 if (!authorities.IsTrusted(signature.PublicKeyBytes)) 26 { 27 return false; 28 } 29 30 var signerId = AuthoritySet.CreateKeyIdentifier(signature.PublicKeyBytes); 31 if (!seenSigners.Add(signerId)) 32 { 33 return false; 34 } 35 36 if (!AuthorityCrypto.VerifyHashedPayload( 37 signature.PublicKeyBytes, 38 resultHash, 39 signature.SignatureBytes)) 40 { 41 return false; 42 } 43 44 validSignatures++; 45 } 46 47 return validSignatures >= policy.RequiredSignatures; 48 } 49 }