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); }
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)); }