Example #1
0
        public bool VerifyTransactionImmediately(TransactionReceipt receipt, bool useNewChainId, bool cacheEnabled)
        {
            if (receipt is null)
            {
                throw new ArgumentNullException(nameof(receipt));
            }

            /* validate transaction hash */
            if (!receipt.Hash.Equals(receipt.FullHash(useNewChainId)))
            {
                return(false);
            }

            try
            {
                /* try to verify signature using public key cache to avoid EC recover */
                if (cacheEnabled && _publicKeyCache.TryGetValue(receipt.Transaction.From, out var publicKey))
                {
                    return(VerifyTransactionImmediately(receipt, publicKey, useNewChainId));
                }

                /* recover EC to get public key from signature to compute address */
                publicKey = receipt.RecoverPublicKey(useNewChainId);
                var address = publicKey.GetAddress();

                /* check if recovered address from public key is valid */
                if (!address.Equals(receipt.Transaction.From))
                {
                    return(false);
                }

                /* try to remember public key for this address */
                if (cacheEnabled)
                {
                    _publicKeyCache.Add(receipt.Transaction.From, publicKey);
                }
            }
            catch (Exception ex)
            {
                Logger.LogWarning($"Failed to verify transaction: {ex}");
                return(false);
            }

            return(true);
        }
Example #2
0
        private OperatingError VerifyInternal(
            TransactionReceipt acceptedTransaction,
            bool canTransactionMissVerification,
            bool useNewChainId
            )
        {
            /* check if the hash matches */
            if (!Equals(acceptedTransaction.Hash, acceptedTransaction.FullHash(useNewChainId)))
            {
                return(OperatingError.HashMismatched);
            }
            /* If it's okay to miss verification, the signature is expected to be empty */
            if (canTransactionMissVerification && acceptedTransaction.Signature.IsZero())
            {
                return(OperatingError.Ok);
            }

            var result = VerifySignature(acceptedTransaction, useNewChainId, true);

            if (result != OperatingError.Ok)
            {
                return(result);
            }
            var transaction = acceptedTransaction.Transaction;

            if (transaction.GasLimit > GasMetering.DefaultBlockGasLimit ||
                transaction.GasLimit < GasMetering.DefaultTxCost)
            {
                return(OperatingError.InvalidGasLimit);
            }

            if (transaction.Value.ToMoney() > Money.MaxValue)
            {
                return(OperatingError.ValueOverflow);
            }
            /* verify transaction via persister */
            return(_transactionExecuter.Verify(transaction));
        }