def test_valid_sender(self):
        # Confirm no error when correct public key is used
        msg = b'this is a pretend merkle tree hash'
        sk, vk = wallet.new()
        signature = wallet.sign(sk, msg)

        timestamp = 'now'
        MerkleSignature.create(sig_hex=signature,
                               timestamp=timestamp,
                               sender=vk)  # no error thrown
    def test_deserialization_valid_json(self):
        # Test valid json throws no errors
        msg = b'this is a pretend merkle tree hash'
        sk, vk = wallet.new()
        signature = wallet.sign(sk, msg)

        d = {
            MerkleSignature.SIG: signature,
            MerkleSignature.TS: 'now',
            MerkleSignature.SENDER: vk
        }
        binary = json.dumps(d).encode()
        MerkleSignature.from_bytes(binary)
Beispiel #3
0
 def signatures(self):
     # Deserialize signatures
     sigs = []
     for i in range(len(self._data[BlockContender.SIGS])):
         sigs.append(
             MerkleSignature.from_bytes(self._data[BlockContender.SIGS][i]))
     return sigs
Beispiel #4
0
 def signatures(self) -> List[MerkleSignature]:
     """
     A list of MerkleSignatures, signed by delegates who were in consensus with this Contender's sender
     """
     # Deserialize signatures
     return [MerkleSignature.from_bytes(self._data[BlockContender.SIGS][i])
             for i in range(len(self._data[BlockContender.SIGS]))]
Beispiel #5
0
    def enter_from_interpret(self):
        assert self.parent.interpreter.queue_size > 0, "Entered consensus state, but interpreter queue is empty!"
        assert self.parent.interpreter.queue_size == BLOCK_SIZE, \
            "Consensus state entered with {} transactions in queue, but the BLOCK_SIZE is {}!"\
            .format(self.parent.interpreter.queue_size, BLOCK_SIZE)

        # Merkle-ize transaction queue and create signed merkle hash
        all_tx = self.parent.interpreter.queue_binary
        self.merkle = MerkleTree.from_raw_transactions(all_tx)
        self.signature = wallet.sign(self.parent.signing_key, self.merkle.root)

        self.log.info("Delegate entering consensus state with merkle hash {}, and latest block hash {}"
                      .format(self.merkle.root_as_hex, self.parent.current_hash))
        self.log.spam("Delegate got merkle leaves {}".format(self.merkle.leaves_as_hex))

        # Create merkle signature message and publish it
        merkle_sig = MerkleSignature.create(sig_hex=self.signature, timestamp='now',
                                            sender=self.parent.verifying_key)
        self.log.debugv("Broadcasting signature {}".format(self.signature))
        self.parent.composer.send_pub_msg(filter=DELEGATE_DELEGATE_FILTER, message=merkle_sig)

        # Now that we've computed/composed the merkle tree hash, validate all our pending signatures
        for sig in [s for s in self.parent.pending_sigs if self.validate_sig(s)]:
            self.signatures.append(sig)

        # Add our own signature
        self.signatures.append(merkle_sig)

        self.check_majority()
Beispiel #6
0
    def enter_from_interpret(self):
        assert self.parent.interpreter.queue_size > 0, "Entered consensus state, but interpreter queue is empty!"

        # Merkle-ize transaction queue and create signed merkle hash
        all_tx = self.parent.interpreter.queue_binary
        self.log.debugv(
            "Delegate got tx from interpreter queue: {}".format(all_tx))
        self.merkle = MerkleTree.from_raw_transactions(all_tx)
        self.log.debugv("Delegate got merkle hash {}".format(
            self.merkle.root_as_hex))
        self.signature = wallet.sign(self.parent.signing_key, self.merkle.root)

        # Create merkle signature message and publish it
        merkle_sig = MerkleSignature.create(sig_hex=self.signature,
                                            timestamp='now',
                                            sender=self.parent.verifying_key)
        self.log.debugv("Broadcasting signature {}".format(self.signature))
        self.parent.composer.send_pub_msg(filter=delegate_delegate,
                                          message=merkle_sig)

        # Now that we've computed/composed the merkle tree hash, validate all our pending signatures
        for sig in [
                s for s in self.parent.pending_sigs if self.validate_sig(s)
        ]:
            self.signatures.append(sig)

        self.check_majority()
 def test_invalid_signature_bad_length(self):
     # Test signature incorrect length (but valid hex)
     sk, vk = wallet.new()
     timestamp = 'now'
     sig = ''.join(('A' for _ in range(100)))
     wrong_len = MerkleSignature.create(sig_hex=sig,
                                        timestamp=timestamp,
                                        sender=vk,
                                        validate=False)
     self.assertRaises(Exception, wrong_len.validate)
Beispiel #8
0
    def validate_sig(self, sig: MerkleSignature) -> bool:
        assert self.merkle is not None, "Cannot validate signature without our merkle set"
        self.log.debugv("Validating signature: {}".format(sig))

        # Verify sender's vk exists in the state
        if sig.sender not in VKBook.get_delegates():
            self.log.warning("Received merkle sig from sender {} who was not registered nodes {}"
                             .format(sig.sender, VKBook.get_delegates()))
            return False

        # Verify we haven't received this signature already
        if sig in self.signatures:
            self.log.warning("Already received a signature from sender {}".format(sig.sender))
            return False

        # Below is just for debugging, so we can see if a signature cannot be verified
        if not sig.verify(self.merkle.root):
            self.log.warning("Delegate could not verify signature! Different Merkle trees.\nSig: {}".format(sig))

        return sig.verify(self.merkle.root)
Beispiel #9
0
    def _create_merkle_sig(self, msg: bytes):
        """
        Helper method to create a MerkleSignature and wallet keys
        :return: A tuple container (MerkleSignature, signing_key, verifying_key)
        """
        assert type(msg) == bytes, "Must pass in bytes"

        sk, vk = wallet.new()
        signature = wallet.sign(sk, msg)
        ms = MerkleSignature.create(sig_hex=signature, timestamp=TIMESTAMP, sender=vk)

        return ms, sk, vk
    def test_serialization(self):
        """
        Tests that a created block data reply successfully serializes and deserializes. The deserialized object should
        have the same properties as the original one before it was serialized.
        """
        msg = b'this is a pretend merkle tree hash'
        sk, vk = wallet.new()
        signature = wallet.sign(sk, msg)

        timestamp = 'now'
        valid_merkle_sig = MerkleSignature.create(sig_hex=signature,
                                                  timestamp=timestamp,
                                                  sender=vk)

        valid_merkle_sig_serialized = valid_merkle_sig.serialize()

        clone = MerkleSignature.from_bytes(valid_merkle_sig_serialized)

        self.assertEqual(valid_merkle_sig.signature, clone.signature)
        self.assertEqual(valid_merkle_sig.timestamp, clone.timestamp)
        self.assertEqual(valid_merkle_sig.sender, clone.sender)
    def test_verify_valid_ms(self):
        """
        Tests that MerkleSignature.verify(...) returns true given a proper msg and vk
        """
        # Test merkle tree verify() validates correct verifying (public) keys
        msg = b'this is a pretend merkle tree hash'
        timestamp = 'now'
        sk, vk = wallet.new()
        signature = wallet.sign(sk, msg)
        ms = MerkleSignature.create(sig_hex=signature,
                                    timestamp=timestamp,
                                    sender=vk)

        self.assertTrue(ms.verify(msg))
    def test_invalid_timestamp(self):
        """
        Test that if the timestamp field is not formatted as expected an error will be thrown
        """
        msg = b'this is a pretend merkle tree hash'
        sk, vk = wallet.new()
        signature = wallet.sign(sk, msg)

        timestamp = 99
        self.assertRaises(
            TypeError,
            MerkleSignature.create(sig_hex=signature,
                                   timestamp=timestamp,
                                   sender=vk))
    def test_invalid_sender_bad_hash(self):
        # Test an error is thrown when created with a sender of not valid hash
        msg = b'this is a pretend merkle tree hash'
        sk, vk = wallet.new()
        signature = wallet.sign(sk, msg)

        timestamp = 'now'
        vk_bad_hash = ''.join(
            'Z' for _ in range(64))  # verifying (public) key with bad hash
        self.assertRaises(
            Exception,
            MerkleSignature.create(sig_hex=signature,
                                   timestamp=timestamp,
                                   sender=vk_bad_hash,
                                   validate=False))
    def test_valid_creation(self):
        """
        Tests that a MerkleSignature created with some argument has the expected properties
        """
        msg = b'this is a pretend merkle tree hash'
        timestamp = 'now'
        sk, vk = wallet.new()
        signature = wallet.sign(sk, msg)
        ms = MerkleSignature.create(sig_hex=signature,
                                    timestamp=timestamp,
                                    sender=vk)

        self.assertEqual(ms.signature, signature)
        self.assertEqual(ms.timestamp, timestamp)
        self.assertEqual(ms.sender, vk)
    def test_invalid_signature_nonhex(self):
        """
        Tests that an error is raised during validation if an invalid signature is passed (nonhex, or length != 128)
        """
        msg = b'this is a pretend merkle tree hash'
        timestamp = 'now'
        sk, vk = wallet.new()

        # Test nonhex signature (but valid length)
        sig = ''.join(('X' for _ in range(128)))
        nonhex = MerkleSignature.create(sig_hex=sig,
                                        timestamp=timestamp,
                                        sender=vk,
                                        validate=False)
        self.assertRaises(Exception, nonhex.validate)
    def test_invalid_sender_wrong_sender(self):
        """
        Tests that an error is raised during creation if an invalid sender field is passed in. A sender should be a
        64 character hex string verifying key.
        """
        # Test an error is thrown when MerkleSignature created with a sender that is not the correct public key
        msg = b'this is a pretend merkle tree hash'
        sk, vk = wallet.new()
        signature = wallet.sign(sk, msg)

        timestamp = 'now'
        vk_bad = wallet.new()[1]  # different verifying (public) key
        bad_public_key = MerkleSignature.create(sig_hex=signature,
                                                timestamp=timestamp,
                                                sender=vk_bad)
        self.assertRaises(Exception, bad_public_key)
Beispiel #17
0
    async def _interpret_next_subtree(self, num_of_batches = 1):
        self.log.debug("Starting to make a new sub-block {} for block {}"
                       .format(self.sub_block_num, self.block_num))
        # get next batch of txns ??  still need to decide whether to unpack a bag or check for end of txn batch
        while(num_of_batches > 0):
            txn = self.pending_txs.popleft()
            if txn == end_of_batch:
                num_of_batches = num_of_batches - 1
            else:
                self.interpreter.interpret(txn)  # this is a blocking call. either async or threads??
            if not self._interpret:         # do we need abort??
                self.interpreter.flush(update_state=False)
                return;

        # Merkle-ize transaction queue and create signed merkle hash
        all_tx = self.interpreter.queue_binary
        self.merkle = MerkleTree.from_raw_transactions(all_tx)
        self.signature = wallet.sign(self.signing_key, self.merkle.root)

        # Create merkle signature message and publish it
        merkle_sig = MerkleSignature.create(sig_hex=self.signature,
                                            timestamp='now',
                                            sender=self.verifying_key)
        self.send_signature(merkle_sig)  # send signature to block manager