示例#1
0
        // Precompiles Below
        /// <summary>
        /// A precompiled contract which uses v,r,s + hash obtained from the message data to perform elliptic curve public key recovery to obtain a senders address.
        /// </summary>
        /// <param name="evm">The Ethereum Virtual Machine instance we are executing inside of.</param>
        private static EVMExecutionResult Precompile_ECRecover(MeadowEVM evm)
        {
            // Charge the gas for the precompile operation before processing.
            evm.GasState.Deduct(GasDefinitions.GAS_PRECOMPILE_ECRECOVER);

            // Obtain a memory representation of our data.
            Span <byte> messageData = new Span <byte>(evm.Message.Data);

            // We extract our signature information from message data (256-bit each)
            Span <byte> hash = messageData.Slice(0, EVMDefinitions.WORD_SIZE);
            BigInteger  v    = BigIntegerConverter.GetBigInteger(messageData.Slice(32, EVMDefinitions.WORD_SIZE));
            BigInteger  r    = BigIntegerConverter.GetBigInteger(messageData.Slice(64, EVMDefinitions.WORD_SIZE));
            BigInteger  s    = BigIntegerConverter.GetBigInteger(messageData.Slice(96, EVMDefinitions.WORD_SIZE));

            // Verify we have a low r, s, and a valid v.
            if (r >= Secp256k1Curve.N || s >= Secp256k1Curve.N || v < 27 || v > 28)
            {
                // We failed v,r,s verification, so we stop executing.
                return(new EVMExecutionResult(evm, null, true));
            }

            // Obtain our recovery id from v.
            byte recoveryID = EthereumEcdsa.GetRecoveryIDFromV((byte)v);

            // Try to get an address from this. If it fails, it will throw an exception.
            byte[] senderAddress = null;
            try
            {
                senderAddress = EthereumEcdsa.Recover(hash, recoveryID, r, s).GetPublicKeyHash();
            }
            catch
            {
                // Recovery failed, so we stop executing.
                return(new EVMExecutionResult(evm, null, true));
            }

            // The address portion is at the end, and we zero out the leading portion.
            for (int i = 0; i < senderAddress.Length - Address.ADDRESS_SIZE; i++)
            {
                senderAddress[i] = 0;
            }

            // Return the sender address
            return(new EVMExecutionResult(evm, senderAddress, true));
        }