It looks like the verify_tx_input function is the smallest atomic function in the library that can validate signatures.
`verify_tx_input : (tx, i, script, sig, pub) -> True/False`
Since you're in the process of learning:
Each input in a transaction has a different signature to the other. Have a look at
https://en.bitcoin.it/wiki/OP_CHECKSIG to see in detail how a transaction is altered to capture all the necessary data for this SIGHASH type. The final step is to sha256d() this modified version, and return this as the hash for ECDSA.
(The SIGHASH flags all have different meanings, but generally speaking, they just mean different data is committed to in the hash. The consequences are beyond the scope of this, but if you read the article, it's the best place to start).
So each transaction input has a signature valid for this [txid, vout, scriptPubKey] combination. Because input signatures are unique to the input, it seems pybitcointools only includes a verify_tx_input function. The likely reason for this is, as you can see, this functions argument signature has 5 arguments.. That's a lot of data just for each input, so a verify_tx() function would depend on a lot of data, which mightn't be available if you're not a full node.
The `txi`, `i`, `script` fields are properties of the transaction you are spending (script == prevOut's scriptPubKey), and are used to produce the hash for ECDSA. Everyone with the blockchain and is doing full validation would now check the signature. The public key is known because it was pushed to the stack either in the prev out scriptPubKey (pay-to-pubkey) or the scriptSig (pay-to-pubkey-hash). And the signature will also be known.
So this is sufficient information for any node on the network to validate a transaction. When you sign a transaction, you need to know the same information, but need to modify the script afterwards, and if it's fully signed, you'll broadcast it.
Note; in bitcoin core, the script language is the means of pushing signatures/pubkeys/opcodes to the stack. After the sig/pubkey is pushed at some point, OP_CHECKSIG is called
On to your code section.
Der_sig appears not to be just the sig - It's the full scriptSig. See the null byte at the start.
The public key, can be 1-of-2, because the scriptPubKey you put up there is a multisig output script. So both public keys will be checked by bitcoin core.
txid = "60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1"
vout = 0
scriptPubKey = '514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae'
outs = [{'value': 1000000, 'script': '76a914660d4ef3a743e3e696ad990364e555c271ad504b88ac'}]
...
# This is actually a der sig plus a byte at the end indicating the SIGHASH type. This must be included.
der_sig = "304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01"
# I just picked a random one from the scriptPubKey, this mightnt return TRUE.
pubkey = "04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4"
# Verify the input
verify_tx_input(txid, vout, scriptPubKey, der_sig, pubkey)
See how I magically defined der_sig and pubkey as constants? Well, there are different output script types, and each is satisfied differently. (in this case, a sig from 1 of 2 keys will do). Depending on the script type, the public keys can be related in different ways. Getting into this is beyond the scope, but studying the OP_CHECKSIG wiki page will show you how it works for pay-to-pubkey-hash.
The multisig-in-the-output-script type is quite similar to this, though calls OP_CHECKMULTISIG. This is mainly just a loop over OP_CHECKSIG.
The next thing to look at this the scripting engine, which ties all of this together.
https://en.bitcoin.it/wiki/Script - at the bottom you'll find step-by-step analysis of how scripts are parsed, ultimately to lead to a CHECKSIG call.
Also - here's the bitcoin core code for OP_CHECKSIG:
https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L827-L860And the actual function TransactionSignatureChecker::CheckSig:
https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1108-L1127