Example #1
0
        public override bool TryAggregatePublicKeys(ReadOnlySpan <byte> publicKeys, Span <byte> destination, out int bytesWritten)
        {
            // This is independent of the keys set, although other parameters (type of curve, variant, scheme, etc) are relevant.

            if (publicKeys.Length % PublicKeyLength != 0)
            {
                throw new ArgumentOutOfRangeException(nameof(publicKeys), publicKeys.Length, $"Public key data must be a multiple of the public key length {PublicKeyLength}.");
            }
            if (destination.Length < PublicKeyLength)
            {
                bytesWritten = 0;
                return(false);
            }

            EnsureInitialised();

            var aggregateBlsPublicKey = default(Bls384Interop.BlsPublicKey);

            for (var index = 0; index < publicKeys.Length; index += PublicKeyLength)
            {
                var publicKeySlice = publicKeys.Slice(index, PublicKeyLength);
                var blsPublicKey   = default(Bls384Interop.BlsPublicKey);
                int publicKeyBytesRead;
                unsafe
                {
                    // Using fixed pointer for input data allows us to pass a slice
                    fixed(byte *publicKeyPtr = publicKeySlice)
                    {
                        publicKeyBytesRead = Bls384Interop.PublicKeyDeserialize(ref blsPublicKey, publicKeyPtr, PublicKeyLength);
                    }
                }
                if (publicKeyBytesRead != PublicKeyLength)
                {
                    throw new Exception($"Error deserializing BLS public key, length: {publicKeyBytesRead}");
                }
                if (index == 0)
                {
                    aggregateBlsPublicKey = blsPublicKey;
                }
                else
                {
                    Bls384Interop.PublicKeyAdd(ref aggregateBlsPublicKey, ref blsPublicKey);
                }
            }

            unsafe
            {
                // Using fixed pointer for output data allows us to write directly to destination
                fixed(byte *destinationPtr = destination)
                {
                    bytesWritten = Bls384Interop.PublicKeySerialize(destinationPtr, PublicKeyLength, ref aggregateBlsPublicKey);
                }
            }
            if (bytesWritten != PublicKeyLength)
            {
                throw new Exception($"Error serializing BLS public key, length: {bytesWritten}");
            }
            return(true);
        }