Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251if P is None:252return False253r = int.from_bytes(sig[0:32], 'big')254if r >= secp256k1.FE.SIZE:255return False256s = int.from_bytes(sig[32:64], 'big')257if s >= ORDER:258return False259e = int.from_bytes(TaggedHash("BIP0340/challenge", sig[0:32] + key + msg), 'big') % ORDER260R = secp256k1.GE.mul((s, secp256k1.G), (-e, P))261if R.infinity or not R.y.is_even():262return False263if r != R.x:264return False265return True267def sign_schnorr(key, msg, aux=None, flip_p=False, flip_r=False):268"""Create a Schnorr signature (see BIP 340)."""270if aux is None:271aux = bytes(32)273assert_equal(len(key), 32)274assert_equal(len(aux), 32)276sec = int.from_bytes(key, 'big')277if sec == 0 or sec >= ORDER:278return None279P = sec * secp256k1.G280if P.y.is_even() == flip_p:281sec = ORDER - sec282t = (sec ^ int.from_bytes(TaggedHash("BIP0340/aux", aux), 'big')).to_bytes(32, 'big')283kp = int.from_bytes(TaggedHash("BIP0340/nonce", t + P.to_bytes_xonly() + msg), 'big') % ORDER284assert_not_equal(kp, 0)285R = kp * secp256k1.G286k = kp if R.y.is_even() != flip_r else ORDER - kp287e = int.from_bytes(TaggedHash("BIP0340/challenge", R.to_bytes_xonly() + P.to_bytes_xonly() + msg), 'big') % ORDER288return R.to_bytes_xonly() + ((k + e * sec) % ORDER).to_bytes(32, 'big')291class TestFrameworkKey(unittest.TestCase):292def test_ecdsa_and_schnorr(self):293"""Test the Python ECDSA and Schnorr implementations."""294byte_arrays = [generate_privkey() for _ in range(3)] + [v.to_bytes(32, 'big') for v in [0, ORDER - 1, ORDER, 2**256 - 1]]295keys = {}296for privkey_bytes in byte_arrays: # build array of key/pubkey pairs297privkey = ECKey()298privkey.set(privkey_bytes, compressed=True)299if privkey.is_valid:300keys[privkey] = privkey.get_pubkey()301for msg in byte_arrays: # test every combination of message, signing key, verification key302for sign_privkey, _ in keys.items():303sig_ecdsa = sign_privkey.sign_ecdsa(msg)304sig_schnorr = sign_schnorr(sign_privkey.get_bytes(), msg)305for verify_privkey, verify_pubkey in keys.items():306verify_xonly_pubkey = verify_pubkey.get_bytes()[1:]307if verify_privkey == sign_privkey:308self.assertTrue(verify_pubkey.verify_ecdsa(sig_ecdsa, msg))309self.assertTrue(verify_schnorr(verify_xonly_pubkey, sig_schnorr, msg))310sig_ecdsa = random_bitflip(sig_ecdsa) # damaging signature should break things311sig_schnorr = random_bitflip(sig_schnorr)312self.assertFalse(verify_pubkey.verify_ecdsa(sig_ecdsa, msg))313self.assertFalse(verify_schnorr(verify_xonly_pubkey, sig_schnorr, msg))315def test_schnorr_testvectors(self):316"""Implement the BIP340 test vectors (read from bip340_test_vectors.csv)."""317num_tests = 0318vectors_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'bip340_test_vectors.csv')319with open(vectors_file, newline='') as csvfile:320reader = csv.reader(csvfile)321next(reader)322for row in reader:323(i_str, seckey_hex, pubkey_hex, aux_rand_hex, msg_hex, sig_hex, result_str, comment) = row324i = int(i_str)325pubkey = bytes.fromhex(pubkey_hex)326msg = bytes.fromhex(msg_hex)327sig = bytes.fromhex(sig_hex)328result = result_str == 'TRUE'329if seckey_hex != '':330seckey = bytes.fromhex(seckey_hex)331pubkey_actual = compute_xonly_pubkey(seckey)[0]332self.assertEqual(pubkey.hex(), pubkey_actual.hex(), "BIP340 test vector %i (%s): pubkey mismatch" % (i, comment))333aux_rand = bytes.fromhex(aux_rand_hex)334try:335sig_actual = sign_schnorr(seckey, msg, aux_rand)336self.assertEqual(sig.hex(), sig_actual.hex(), "BIP340 test vector %i (%s): sig mismatch" % (i, comment))337except RuntimeError as e:338self.fail("BIP340 test vector %i (%s): signing raised exception %s" % (i, comment, e))339result_actual = verify_schnorr(pubkey, sig, msg)340if result:341self.assertEqual(result, result_actual, "BIP340 test vector %i (%s): verification failed" % (i, comment))342else:343self.assertEqual(result, result_actual, "BIP340 test vector %i (%s): verification succeeded unexpectedly" % (i, comment))344num_tests += 1345self.assertTrue(num_tests >= 15) # expect at least 15 test vectors
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.