scriptSig: <pubKey>
scriptPubKey: <pubKey> OP_EQUALVERIFY
The stack has <pubKey>, <pubKey> and then OP_EQUALVERIFY. So why, does it not return TRUE, even when the recent two elements in the stack are equal?
OP_EQUALVERIFY
has two possible outcomes:
For a script execution to be treated as successful, it must end with a non-empty stack whose top element is not 0. In your case, the stack is empty after execution, and thus the script execution is treated as failed.
You probably want to use OP_EQUAL
instead, which puts 0 or 1 on the stack (rather than aborting or doing nothing).
Andreas Antonopoulos discusses the VERIFY suffix here.
Anything that has VERIFY will only continue execution of the Script if the outcome of the conditional operator is TRUE in which case it will not push that TRUE back to the stack, it will simply continue execution.
This StackExchange post may also be of interest.
The code for OP_EQUALVERIFY in the Bitcoin Core codebase is here.