def basicSchnorrSigning(self): # First try a canned sig (taken from schnorr.py) privkey = bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747") pubkey = schnorr.getpubkey(privkey, compressed=True) assert pubkey == bytes.fromhex( "030b4c866585dd868a9d62348a9cd008d6a312937048fff31670e7e920cfc7a744" ) msg = b"Very deterministic message" msghash = hash256(msg) assert msghash == bytes.fromhex( "5255683da567900bfd3e786ed8836a4e7763c221bf1ac20ece2a5171b9199e8a") sig = schnorr.sign(privkey, msghash) assert sig == bytes.fromhex( "2c56731ac2f7a7e7f11518fc7722a166b02438924ca9d8b4d111347b81d0717571846de67ad3d913a8fdf9d8f3f73161a4c48ae81cb183b214765feb86e255ce" ) sig2 = cashlib.signHashSchnorr(privkey, msghash) assert sig2 == sig logging.info("random Schnorr signature comparison") # Next try random signatures for i in range(1, 1000): privkey = cashlib.randombytes(32) pubkey = schnorr.getpubkey(privkey, compressed=True) pubkey2 = cashlib.pubkey(privkey) assert pubkey == pubkey2 msg = cashlib.randombytes(random.randint(0, 10000)) hsh = cashlib.hash256(msg) sigpy = schnorr.sign(privkey, hsh) sigcashlib = cashlib.signHashSchnorr(privkey, hsh) assert sigpy == sigcashlib
def pubkeySearch(self): print("pid: ", os.getpid()) privkey = cashlib.randombytes(32) pubkey = schnorr.getpubkey(privkey, compressed=True) lens = array.array("Q", [0 for i in range(0, 101)]) data = 1 while 1: databytes = struct.pack(">Q", data) sig = cashlib.signData(databytes, privkey) l = len(sig) if l == 64: print("data: ", data, " ", hexlify(databytes)) print("sig: ", hexlify(sig)) print("privkey:", hexlify(privkey)) pdb.set_trace() lens[l] += 1 data += 1 if ((data & 16383) == 0): print(data) print(lens[60:])
def run_test(self): node = self.nodes[0] # Create a fake node and connect it to our real node. poll_node = TestNode() node.add_p2p_connection(poll_node) poll_node.wait_for_verack() poll_node.sync_with_ping() # Get our own node id so we can use it later. nodeid = node.getpeerinfo()[-1]['id'] # Generate many block and poll for them. address = node.get_deterministic_priv_key().address node.generatetoaddress(100, address) fork_node = self.nodes[1] # Make sure the fork node has synced the blocks sync_blocks([node, fork_node]) # Get the key so we can verify signatures. avakey = bytes.fromhex(node.getavalanchekey()) self.log.info("Poll for the chain tip...") best_block_hash = int(node.getbestblockhash(), 16) poll_node.send_poll([best_block_hash]) def assert_response(expected): response = poll_node.wait_for_avaresponse() r = response.response assert_equal(r.cooldown, 0) # Verify signature. assert schnorr.verify(response.sig, avakey, r.get_hash()) votes = r.votes assert_equal(len(votes), len(expected)) for i in range(0, len(votes)): assert_equal(repr(votes[i]), repr(expected[i])) assert_response([AvalancheVote(BLOCK_ACCEPTED, best_block_hash)]) self.log.info("Poll for a selection of blocks...") various_block_hashes = [ int(node.getblockhash(0), 16), int(node.getblockhash(1), 16), int(node.getblockhash(10), 16), int(node.getblockhash(25), 16), int(node.getblockhash(42), 16), int(node.getblockhash(96), 16), int(node.getblockhash(99), 16), int(node.getblockhash(100), 16), ] poll_node.send_poll(various_block_hashes) assert_response( [AvalancheVote(BLOCK_ACCEPTED, h) for h in various_block_hashes]) self.log.info( "Poll for a selection of blocks, but some are now invalid...") invalidated_block = node.getblockhash(76) node.invalidateblock(invalidated_block) # We need to send the coin to a new address in order to make sure we do # not regenerate the same block. node.generatetoaddress( 26, 'bchreg:pqv2r67sgz3qumufap3h2uuj0zfmnzuv8v7ej0fffv') node.reconsiderblock(invalidated_block) poll_node.send_poll(various_block_hashes) assert_response([ AvalancheVote(BLOCK_ACCEPTED, h) for h in various_block_hashes[:5] ] + [ AvalancheVote(BLOCK_REJECTED, h) for h in various_block_hashes[-3:] ]) self.log.info("Poll for unknown blocks...") various_block_hashes = [ int(node.getblockhash(0), 16), int(node.getblockhash(25), 16), int(node.getblockhash(42), 16), various_block_hashes[5], various_block_hashes[6], various_block_hashes[7], random.randrange(1 << 255, (1 << 256) - 1), random.randrange(1 << 255, (1 << 256) - 1), random.randrange(1 << 255, (1 << 256) - 1), ] poll_node.send_poll(various_block_hashes) assert_response([ AvalancheVote(BLOCK_ACCEPTED, h) for h in various_block_hashes[:3] ] + [ AvalancheVote(BLOCK_REJECTED, h) for h in various_block_hashes[3:6] ] + [ AvalancheVote(BLOCK_UNKNOWN, h) for h in various_block_hashes[-3:] ]) self.log.info("Trigger polling from the node...") # duplicate the deterministic sig test from src/test/key_tests.cpp privkey = bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747") pubkey = schnorr.getpubkey(privkey, compressed=True) node.addavalanchepeer(nodeid, pubkey.hex()) # Make sure the fork node has synced the blocks sync_blocks([node, fork_node]) # Create a fork 2 blocks deep. This should trigger polling. fork_node.invalidateblock(fork_node.getblockhash(100)) fork_address = fork_node.get_deterministic_priv_key().address fork_node.generatetoaddress(2, fork_address) def can_find_block_in_poll(hash): poll = poll_node.wait_for_avapoll() invs = poll.invs votes = [] found_hash = False for inv in invs: # Look for what we expect if inv.hash == hash: found_hash = True # Vote yes to everything votes.append(AvalancheVote(BLOCK_ACCEPTED, inv.hash)) poll_node.send_avaresponse(poll.round, votes, privkey) return found_hash # Because the new tip is a deep reorg, the node should start to poll # for it. hash_to_find = int(fork_node.getbestblockhash(), 16) wait_until(lambda: can_find_block_in_poll(hash_to_find), timeout=5) # To verify that responses are processed, do it a few more times. for _ in range(10): wait_until(lambda: can_find_block_in_poll(hash_to_find), timeout=5)
def run_test(self): node = self.nodes[0] # Build a fake quorum of nodes. quorum = [] for i in range(0, 8): n = TestNode() quorum.append(n) node.add_p2p_connection(n) n.wait_for_verack() # Get our own node id so we can use it later. n.nodeid = node.getpeerinfo()[-1]['id'] # Pick on node from the quorum for polling. poll_node = quorum[0] # Generate many block and poll for them. address = node.get_deterministic_priv_key().address node.generatetoaddress(100, address) fork_node = self.nodes[1] # Make sure the fork node has synced the blocks self.sync_blocks([node, fork_node]) # Get the key so we can verify signatures. avakey = bytes.fromhex(node.getavalanchekey()) self.log.info("Poll for the chain tip...") best_block_hash = int(node.getbestblockhash(), 16) poll_node.send_poll([best_block_hash]) def assert_response(expected): response = poll_node.wait_for_avaresponse() r = response.response assert_equal(r.cooldown, 0) # Verify signature. assert schnorr.verify(response.sig, avakey, r.get_hash()) votes = r.votes assert_equal(len(votes), len(expected)) for i in range(0, len(votes)): assert_equal(repr(votes[i]), repr(expected[i])) assert_response([AvalancheVote(BLOCK_ACCEPTED, best_block_hash)]) self.log.info("Poll for a selection of blocks...") various_block_hashes = [ int(node.getblockhash(0), 16), int(node.getblockhash(1), 16), int(node.getblockhash(10), 16), int(node.getblockhash(25), 16), int(node.getblockhash(42), 16), int(node.getblockhash(96), 16), int(node.getblockhash(99), 16), int(node.getblockhash(100), 16), ] poll_node.send_poll(various_block_hashes) assert_response( [AvalancheVote(BLOCK_ACCEPTED, h) for h in various_block_hashes]) self.log.info( "Poll for a selection of blocks, but some are now invalid...") invalidated_block = node.getblockhash(76) node.invalidateblock(invalidated_block) # We need to send the coin to a new address in order to make sure we do # not regenerate the same block. node.generatetoaddress( 26, 'bchreg:pqv2r67sgz3qumufap3h2uuj0zfmnzuv8v7ej0fffv') node.reconsiderblock(invalidated_block) poll_node.send_poll(various_block_hashes) assert_response([ AvalancheVote(BLOCK_ACCEPTED, h) for h in various_block_hashes[:5] ] + [ AvalancheVote(BLOCK_REJECTED, h) for h in various_block_hashes[-3:] ]) self.log.info("Poll for unknown blocks...") various_block_hashes = [ int(node.getblockhash(0), 16), int(node.getblockhash(25), 16), int(node.getblockhash(42), 16), various_block_hashes[5], various_block_hashes[6], various_block_hashes[7], random.randrange(1 << 255, (1 << 256) - 1), random.randrange(1 << 255, (1 << 256) - 1), random.randrange(1 << 255, (1 << 256) - 1), ] poll_node.send_poll(various_block_hashes) assert_response([ AvalancheVote(BLOCK_ACCEPTED, h) for h in various_block_hashes[:3] ] + [ AvalancheVote(BLOCK_REJECTED, h) for h in various_block_hashes[3:6] ] + [ AvalancheVote(BLOCK_UNKNOWN, h) for h in various_block_hashes[-3:] ]) self.log.info("Trigger polling from the node...") # duplicate the deterministic sig test from src/test/key_tests.cpp privkey = bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747") pubkey = schnorr.getpubkey(privkey, compressed=True) # Activate the quorum. for n in quorum: node.addavalanchepeer(n.nodeid, pubkey.hex()) def can_find_block_in_poll(hash, resp=BLOCK_ACCEPTED): found_hash = False for n in quorum: poll = n.get_avapoll_if_available() # That node has not received a poll if poll is None: continue # We got a poll, check for the hash and repond votes = [] for inv in poll.invs: # Vote yes to everything r = BLOCK_ACCEPTED # Look for what we expect if inv.hash == hash: r = resp found_hash = True votes.append(AvalancheVote(r, inv.hash)) n.send_avaresponse(poll.round, votes, privkey) return found_hash # Now that we have a peer, we should start polling for the tip. hash_tip = int(node.getbestblockhash(), 16) wait_until(lambda: can_find_block_in_poll(hash_tip), timeout=5) # Make sure the fork node has synced the blocks self.sync_blocks([node, fork_node]) # Create a fork 2 blocks deep. This should trigger polling. fork_node.invalidateblock(fork_node.getblockhash(100)) fork_address = fork_node.get_deterministic_priv_key().address fork_node.generatetoaddress(2, fork_address) # Because the new tip is a deep reorg, the node will not accept it # right away, but poll for it. def parked_block(blockhash): for tip in node.getchaintips(): if tip["hash"] == blockhash: assert tip["status"] != "active" return tip["status"] == "parked" return False fork_tip = fork_node.getbestblockhash() wait_until(lambda: parked_block(fork_tip)) self.log.info("Answer all polls to finalize...") hash_to_find = int(fork_tip, 16) def has_accepted_new_tip(): can_find_block_in_poll(hash_to_find) return node.getbestblockhash() == fork_tip # Because everybody answers yes, the node will accept that block. wait_until(has_accepted_new_tip, timeout=15) assert_equal(node.getbestblockhash(), fork_tip)