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

ECRecover contract upgrade #414

Closed
wants to merge 17 commits into from

Conversation

YakupIpek
Copy link
Member

The stratisproject/StratisBitcoinFullNode#4194 moved here.

This pr needs to have package from stratisproject/Stratis.SmartContracts#13

This pr has been reviewed actually and should to be complete but it was require to have hard-fork because upgrade needed on Stratis.SmartContracts assemblies.

Basically EcRecoverProvider.SignMessage(privateKey, message) returns a signature that we can recover PubKey address and we can do this via ECRecoverProvider.GetSigner(message, offChainSignature) in the smart contract code.

I reviewed&tested it and i don't have anything to add.

I am going to remove dev prefix from version(2.0.1-dev) if it is approved.

codingupastorm and others added 10 commits February 8, 2021 15:42
# Conflicts:
#	src/Stratis.Bitcoin.Features.SmartContracts.Tests/Stratis.Bitcoin.Features.SmartContracts.Tests.csproj
#	src/Stratis.Bitcoin.Features.SmartContracts/Stratis.Bitcoin.Features.SmartContracts.csproj
#	src/Stratis.SmartContracts.CLR.Validation/Stratis.SmartContracts.CLR.Validation.csproj
Copy link
Contributor

@quantumagi quantumagi left a comment

Choose a reason for hiding this comment

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

LGTM. Can merge when CI passes.

/// <returns>The base58 address for the signer of a signature.</returns>
public Address GetSigner(byte[] message, byte[] signature)
{
// TODO: Error handling for incorrect signature format etc.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this needs to be resolved before this can be used in production.

Copy link
Member Author

Choose a reason for hiding this comment

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

@rowandh PubKey.RecoverCompact already detects incorrect format and raise an exception.

There is something else to do in here ?

@quantumagi
Copy link
Contributor

quantumagi commented Apr 7, 2021

Perhaps include support for VerifySignatures into this PR. See https://github.com/stratisproject/Stratis.SmartContracts/blob/1d30c10805b7b2b4c77440068642614394c54b28/Stratis.SmartContracts/IEcRecoverProvider.cs.

        private byte[][] DeserializeSignatures(byte[] signatures)
        {
            const int signatureLength = 65;
            const int minHeaderByte = 27;
            const int maxHeaderByte = 34;
            int cnt = signatures.Length / signatureLength;
            Guard.Assert(signatures.Length == signatureLength * cnt);
            var buffer = new byte[cnt][];
            for (int i = 0; i < cnt; i++)
            {
                Array.Copy(signatures, i * signatureLength, buffer[i], 0, signatureLength);
                Guard.Assert(buffer[i][0] >= minHeaderByte && buffer[i][0] <= maxHeaderByte);
            }
            return buffer;
        }

        /// <summary>
        /// Takes a message and signatures and returns the list of addresses that produced the signatures.
        /// </summary>
        /// <param name="message">The message that was signed.</param>
        /// <param name="signatures">The list of signatures of the message.</param>
        /// <param name="addresses">If not <c>null</c> the addresses returned are intersected with these addresses.</param>
        /// <returns>The list of addresses that produced the signatures and constrained to the list provided in <paramref name="addresses"/> if not <c>null</c>.</returns>
        public Address[] VerifySignatures(byte[] signatures, byte[] message, Address[] addresses = null)
        {
            Guard.NotNull(message, nameof(message));
            Guard.NotNull(signatures, nameof(signatures));
            var keyIds = DeserializeSignatures(signatures)
                .Select(s => PubKey.RecoverFromMessage(message, Encoders.Base64.EncodeData(s)).Hash);
            if (addresses != null)
                keyIds = keyIds.Intersect(addresses.Select(a => new KeyId(a.ToBytes())));
            return keyIds.Select(s => s.ToBytes().ToAddress()).ToArray();
        }

uint256 hashedUint256 = GetUint256FromMessage(message);
PubKey pubKey = PubKey.RecoverCompact(hashedUint256, signature);

return pubKey.GetAddress(this.network).ToString().ToAddress(this.network);
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps this conversion can be done without using this.network.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants