예제 #1
0
    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
예제 #2
0
 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:])
예제 #3
0
    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)
예제 #4
0
    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)