def test_validate_linked_double_pay_fraud(self): db = self.MockDatabase() (block1, _, _, _) = TestBlocks.setup_validate() # Act db.add_block(block1) db.add_block(MultiChainBlock.create(db, block1.link_public_key, block1)) block2 = MultiChainBlock.create(db, block1.link_public_key, block1) result = block2.validate(db) self.assertEqual(result[0], ValidationResult.invalid) self.assertIn("Double countersign fraud", result[1])
def test_validate_linked_valid(self): db = self.MockDatabase() (block1, block2, _, _) = TestBlocks.setup_validate() db.add_block(block2) # Act db.add_block(MultiChainBlock.create(db, block1.link_public_key, block1)) result = block1.validate(db) self.assertEqual(result[0], ValidationResult.valid)
def test_create_genesis(self): key = ECCrypto().generate_key(u"curve25519") db = self.MockDatabase() block = MultiChainBlock.create(db, key.pub().key_to_bin(), link=None) self.assertEqual(block.previous_hash, GENESIS_HASH) self.assertEqual(block.sequence_number, GENESIS_SEQ) self.assertEqual(block.public_key, key.pub().key_to_bin()) self.assertEqual(block.signature, EMPTY_SIG)
def test_create_next(self): db = self.MockDatabase() prev = TestBlock() prev.sequence_number = GENESIS_SEQ db.add_block(prev) block = MultiChainBlock.create(db, prev.public_key, link=None) self.assertEqual(block.previous_hash, prev.hash) self.assertEqual(block.sequence_number, 2) self.assertEqual(block.public_key, prev.public_key)
def test_validate_linked_mismatch(self): db = self.MockDatabase() (block1, block2, _, _) = TestBlocks.setup_validate() # Act # db.add_block(MultiChainBlock.create(db, block1.link_public_key, block1)) db.add_block(block1) block3 = MultiChainBlock.create(db, block2.link_public_key, block1) result = block3.validate(db) self.assertEqual(result[0], ValidationResult.invalid) self.assertIn("Public key mismatch on linked block", result[1])
def test_validate_linked_down(self): db = self.MockDatabase() (block1, block2, _, _) = TestBlocks.setup_validate() db.add_block(block2) # Act db.add_block(MultiChainBlock.create(db, block1.link_public_key, block1)) block1.down -= 5 result = block1.validate(db) self.assertEqual(result[0], ValidationResult.invalid) self.assertIn("Down/up mismatch on linked block", result[1])
def test_create_link_genesis(self): key = ECCrypto().generate_key(u"curve25519") db = self.MockDatabase() link = TestBlock() db.add_block(link) block = MultiChainBlock.create(db, key.pub().key_to_bin(), link=link) self.assertEqual(block.previous_hash, GENESIS_HASH) self.assertEqual(block.sequence_number, GENESIS_SEQ) self.assertEqual(block.public_key, key.pub().key_to_bin()) self.assertEqual(block.link_public_key, link.public_key) self.assertEqual(block.link_sequence_number, link.sequence_number)
def sign_block(self, candidate, public_key=None, bytes_up=None, bytes_down=None, linked=None): """ Create, sign, persist and send a block signed message :param candidate: The peer with whom you have interacted, as a dispersy candidate :param bytes_up: The bytes you have uploaded to the peer in this interaction :param bytes_down: The bytes you have downloaded from the peer in this interaction :param linked: The block that the requester is asking us to sign """ # NOTE to the future: This method reads from the database, increments and then writes back. If in some future # this method is allowed to execute in parallel, be sure to lock from before .create up to after .add_block assert bytes_up is None and bytes_down is None and linked is not None or \ bytes_up is not None and bytes_down is not None and linked is None, \ "Either provide a linked block or byte counts, not both" assert linked is None or linked.link_public_key == self.my_member.public_key, \ "Cannot counter sign block not addressed to self" assert linked is None or linked.link_sequence_number == UNKNOWN_SEQ, \ "Cannot counter sign block that is not a request" block = MultiChainBlock.create(self.persistence, self.my_member.public_key, linked) if linked is None: block.up = bytes_up block.down = bytes_down block.total_up += bytes_up block.total_down += bytes_down block.link_public_key = public_key block.sign(self.my_member.private_key) validation = block.validate(self.persistence) self.logger.info("Signed block to %s (%s) validation result %s", block.link_public_key.encode("hex")[-8:], block, validation) if validation[0] != ValidationResult.partial_next and validation[ 0] != ValidationResult.valid: self.logger.error("Signed block did not validate?! Result %s", repr(validation)) else: self.persistence.add_block(block) self.send_block(candidate, block)