Title: Extract the Public Key from a "CScript CTxIn::scriptSig" object Post by: noureddin_regula on April 09, 2022, 02:41:42 AM In Bitcoin Core code, how can the Public Key ("class CPubKey" or "class XOnlyPubKey") be extracted from a "CScript CTxIn::scriptSig" object ?
Title: Re: Extract the Public Key from a "CScript CTxIn::scriptSig" object Post by: pooya87 on April 09, 2022, 03:48:55 AM You first have to know what the content of a scriptsig is. It could simply be empty, a wrapped witness program or any other script without a public key. Then you have to evaluate the whole script (scriptpub + scriptsig) and when you reach one of the OP_CHECK(MULTI)SIG(VERIFY) codes figure out which item(s) on is the public key.
Title: Re: Extract the Public Key from a "CScript CTxIn::scriptSig" object Post by: noureddin_regula on April 09, 2022, 04:27:46 AM Thanks for your reply.
But I assume the steps you mentioned already exists in the code (or something like that) as the "src/script/interpreter.cpp::EvalChecksig(...)" needs the public key(s) to process the OP_CHECKSIG and OP_CHECKMULTISIG operation codes. Code: bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror) But I couldn't find the part of the code where the public key is extracted from the scriptSig and inserted into the script stack. I've tried debugging and grep to "stack.push_back(" but no good results. I'm particularly interested in extracting the public key of "CScript CTxIn::scriptSig" from P2PKH, P2WPKH, P2TR. Title: Re: Extract the Public Key from a "CScript CTxIn::scriptSig" object Post by: pooya87 on April 09, 2022, 04:47:41 AM The stacktop(-1) method is peeking at the topmost element on the stack and interprets it as a public key without removing it from the stack. The popstack(stack); removes it from the stack later on.
If you want to extract it, you could potentially change the code and add a line right after the valtype& vchPubKey = stacktop(-1); and get the public key. Code: CPubKey pubkey(vchPubKey); I'm particularly interested in extracting the public key of "CScript CTxIn::scriptSig" from P2PKH, P2WPKH, P2TR. 2) Legacy scripts (P2PKH and P2SH) will have public key in their signature script or it may already by in the pubkey script (P2PK).1) SegWit version 0 scripts will have the pubkey (+ everything else) always in their witness and the signature script will be empty for P2WPKH and P2WSH and will contain the witness program for wrapped SegWit ie. P2SH-P2PKH and P2SH-P2WSH 3) Taproot scripts will have a tweaked public key in their pubkey script (the output) and the signature (+ everything else) in their witness For all cases OP_CHECKSIG(VERIFY) could be run and consumes a public key. For 1 & 2 OP_CHECKMULTISIG(VERIFY) could be run and consumes one or more public keys. For 3 OP_CHECKSIGADD could also be run if it is found in the script that consumes a public key. Why are you trying to extract public keys? Title: Re: Extract the Public Key from a "CScript CTxIn::scriptSig" object Post by: noureddin_regula on April 09, 2022, 05:29:04 AM Thanks for your detailed answer.
Yes, I understand that "CPubKey pubkey(vchPubKey);" would work on "bool EvalScript(...)", but I am trying to extract the public key from "CScript CTxIn::scriptSig" inside "CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, ...)", where I have access to the scriptSig from the transaction inputs ("CTransaction::vin") and to the "CWallet::chain()", where I can retrieve the coins (`class Coin`) related to an input and get the "Coin::CTxOut:: scriptPubKey" if necessary (perhaps to infer the transaction type?). 1) and 3) For SegWit version 0 scripts (P2PWKH and P2SH-P2WPKH), I think the data will be in "CScriptWitness CTxIn::scriptWitness" and not in "CScript scriptSig". The same may apply to P2TR transactions (SegWit version 1). 2) For legacy address (P2PKH, P2SH and P2PK) I think it will be in "CScript CTxIn::scriptSig". So I would like to extract the Public Key inside "CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, ...)". The reason is to do an ECDH operation with other keys. I think this issue is already solved at some point in the code as it is necessary to evaluate the script, but I haven't been able to find this logic so far. Title: Re: Extract the Public Key from a "CScript CTxIn::scriptSig" object Post by: alexeyneu on April 12, 2022, 08:50:27 AM you need tx as block of bytes. Then you can go after pubscript.
Code: struct Transaction { and then Code: transaction.pubkeyScript[0] = 0x41; So reverse-engineer this. https://github.com/alexeyneu/BlockZero/blob/master/BlockZero.cpp#L17-L29 |