def test_missing_hash(self): """ Test Valid rollback after receiving """ db = MockDatabase() # Receive money B1 = TestBlock( block_type=BlockTypes.TRANSFER, transaction={'balance': 0, 'amount': 10}, ) A1 = TestBlock( block_type=BlockTypes.TRANSFER, transaction={'balance': 0, 'amount': 10}, linked=B1 ) # db.add_block(B1) #TODO: B1 should really exist or be crawled for (isnt right now) db.add_block(A1) result, errors = A1.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) # roll back the transaction A2 = TestBlock( block_type=BlockTypes.ROLLBACK, transaction={'balance': 0, 'amount': 10}, previous = A1) result, errors = A2.validate_transaction(db) self.assertEqual(result, ValidationResult.invalid) self.assertIsInstance(errors[0], EuroTokenRollBackBlock.MissingTransactionHash)
def test_invalid_amount(self): """ Test amount doesnt match rolled back transaction """ db = MockDatabase() # Receive money B1 = TestBlock( block_type=BlockTypes.TRANSFER, transaction={'balance': 0, 'amount': 10}, ) A1 = TestBlock( block_type=BlockTypes.TRANSFER, transaction={'balance': 0, 'amount': 10}, linked=B1 ) # db.add_block(B1) db.add_block(A1) result, errors = A1.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) # roll back the transaction A2 = TestBlock( block_type=BlockTypes.ROLLBACK, transaction={'balance': 5, 'amount': 5, 'transaction_hash': hexlify(A1.hash)}, previous = A1) result, errors = A2.validate_transaction(db) self.assertEqual(result, ValidationResult.invalid) self.assertIsInstance(errors[0], EuroTokenRollBackBlock.InvalidRollback)
def test_missing_previous(self): """ Test validating a block that points towards a missing block """ db = MockDatabase() G = db.owner A1 = TestBlock(block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}, links=G) result, errors = A1.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, []) # db.add_block(A1) MISSING!!! A2 = TestBlock(block_type="NonEurotoken", transaction={}, previous=A1) db.add_block(A2) A3 = TestBlock(block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}, previous=A2, links=G) result, errors = A3.validate_transaction(db) self.assertEqual(result, ValidationResult.missing) self.assertEqual(errors, [ BlockRange(A1.public_key, A1.sequence_number, A1.sequence_number) ])
def test_valid_creation(self): """ Test Valid send after receiving """ db = MockDatabase() G = db.owner G1 = TestBlock( key=G, block_type=BlockTypes.CREATION, transaction={'amount': 10}, ) A1 = TestBlock(block_type=BlockTypes.CREATION, transaction={'amount': 10}, linked=G1) # A1.link_pk = G1.public_key db.add_block(G1) db.add_block(A1) result, errors = A1.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) A2 = TestBlock(block_type=BlockTypes.CHECKPOINT, transaction={'balance': 10}, previous=A1, links=G) result, errors = A2.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid)
def test_double_validate_skip_non_eurotoken(self): """ Test validating a block that points towards a previous block with a non eurotoken block in between """ db = MockDatabase() G = db.owner A1 = TestBlock(block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}, links=G) result, errors = A1.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, []) db.add_block(A1) A2 = TestBlock(block_type="NonEurotoken", transaction={}, previous=A1) db.add_block(A2) A3 = TestBlock(block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}, previous=A2, links=G) result, errors = A3.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, [])
def test_valid_balance_genesis(self): """ Test validating a genesis block with 0 balance """ db = MockDatabase() prev = TestBlock(block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}) result, errors = prev.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, []) db.add_block(prev)
def test_fake_creation_rollback(self): """ Test that a creation without its linked is rejected """ db = MockDatabase() G = db.owner A = TestWallet() G1 = TestBlock( key = G, block_type=BlockTypes.CREATION, transaction={'amount': 10}, ) A1 = TestBlock( key=A, block_type=BlockTypes.CREATION, transaction={'amount': 10}, linked=G1 ) # A1.link_pk = G1.public_key # db.add_block(G1) SEND DOENST EXIST db.add_block(A1) result, errors = A1.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) A2 = TestBlock( block_type=BlockTypes.ROLLBACK, transaction={'balance': 0, 'amount': 10, 'transaction_hash': hexlify(A1.hash)}, previous=A1, links=A ) result, errors = A2.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) db.add_block(A2) A3 = TestBlock( block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}, previous=A2, links=G ) result, errors = A3.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid)
def test_double_validate(self): """ Test validating a block that points towards a previous block """ db = MockDatabase() prev = TestBlock(block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}) result, errors = prev.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, []) db.add_block(prev) block = TestBlock(block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}, previous=prev) result, errors = block.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, [])
def test_missing_validated_balance(self): """ Test validating a genesis block without a balance """ db = MockDatabase() G = db.owner A = TestWallet() G1 = TestBlock(key=G, block_type=BlockTypes.CREATION, transaction={'amount': 10}, links=A) result, errors = G1.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, []) db.add_block(G1) A1 = TestBlock(key=A, block_type=BlockTypes.CREATION, transaction={'amount': 10}, linked=G1) result, errors = A1.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, []) db.add_block(A1) A2 = TestBlock(block_type=BlockTypes.TRANSFER, transaction={ 'balance': 5, 'amount': 5 }, previous=A1) result, errors = A2.validate_transaction(db) self.assertEqual(result, ValidationResult.invalid) self.assertIsInstance(errors[0], EuroTokenBlock.InsufficientValidatedBalance)
def test_get_balance_receive_block_with_crawl(self): db = MockDatabase() A = TestWallet() A1 = TestBlock(key=A, block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}) result, errors = A1.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, []) db.add_block(A1) B2 = getWalletBlockWithBalance(10, db) B3 = TestBlock(block_type=BlockTypes.TRANSFER, transaction={ 'balance': 5, 'amount': 5 }, previous=B2, links=A) result, errors = B3.validate_transaction(db) self.assertEqual(result, ValidationResult.valid) self.assertEqual(errors, []) db.add_block(B3) A2 = TestBlock(block_type=BlockTypes.TRANSFER, transaction={ 'balance': 5, 'amount': 5 }, previous=A1, linked=B3) balance = A2.get_balance(db) self.assertEqual(balance, 5)
def test_invalid_transaction_and_incorrect_rollback(self): db = MockDatabase() G = db.owner A = TestWallet() B = TestWallet() # B receives money and does not verify X2 = getWalletBlockWithBalance(10, db) X3 = TestBlock( block_type=BlockTypes.TRANSFER, transaction={'amount': 5, 'balance': 5}, links = B, previous=X2 ) result, errors = X3.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) db.add_block(X3) B1 = TestBlock( key = B, block_type=BlockTypes.TRANSFER, transaction={'amount': 5, 'balance': 5}, linked = X3 ) result, errors = B1.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) # db.add_block(B1) we dont have B1 # B sends the money to A and A accepts (A shouldn't have) B2 = TestBlock( block_type=BlockTypes.TRANSFER, transaction={'amount': 5, 'balance': 0}, previous=B1, links=A ) result, errors = B2.validate_transaction(db) self.assertEqual(result, ValidationResult.missing) #Note send is invalid self.assertEqual(errors, [BlockRange(B1.public_key, B1.sequence_number, B1.sequence_number)]) db.add_block(B2) #added without crawl, because provided by A A1 = TestBlock( key = A, block_type=BlockTypes.TRANSFER, transaction={'amount': 5, 'balance': 0}, linked = B2 ) result, errors = A1.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) db.add_block(A1) # A tries to verify and fails A2 = TestBlock( block_type=BlockTypes.CHECKPOINT, transaction={'balance': 5}, previous=A1, links=G ) result, errors = A2.validate_transaction(db) self.assertEqual(result, ValidationResult.missing) self.assertEqual(errors, [BlockRange(B1.public_key, B1.sequence_number, B1.sequence_number)]) db.add_block(A2) # A adds an incorrect rollback block A3 = TestBlock( block_type=BlockTypes.ROLLBACK, transaction={'balance': 1, 'amount': 4, 'transaction_hash': hexlify(A1.hash)}, previous=A2, links=A ) result, errors = A3.validate_transaction(db) self.assertEqual(result, ValidationResult.invalid) self.assertIsInstance(errors[0], EuroTokenBlock.InvalidRollback) db.add_block(A3, True) # force in, this could happen if the linked block was missing at the time of arrival # A tries to verify and fails A4 = TestBlock( block_type=BlockTypes.CHECKPOINT, transaction={'balance': 1}, previous=A3, links=G ) result, errors = A4.validate_transaction(db) self.assertEqual(result, ValidationResult.invalid) self.assertIsInstance(errors[0], EuroTokenBlock.InvalidRollback)
def test_invalid_transaction_and_rollback(self): db = MockDatabase() G = db.owner A = TestWallet() B = TestWallet() # B receives money and does not verify X2 = getWalletBlockWithBalance(10, db) X3 = TestBlock( block_type=BlockTypes.TRANSFER, transaction={'amount': 5, 'balance': 5}, links = B, previous=X2 ) result, errors = X3.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) db.add_block(X3) B1 = TestBlock( key = B, block_type=BlockTypes.TRANSFER, transaction={'amount': 5, 'balance': 5}, linked = X3 ) result, errors = B1.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) # db.add_block(B1) #we dont have B1 # B sends the money to A and A accepts (A shouldn't have) B2 = TestBlock( block_type=BlockTypes.TRANSFER, transaction={'amount': 5, 'balance': 0}, previous=B1, links=A ) result, errors = B2.validate_transaction(db) self.assertEqual(result, ValidationResult.missing) self.assertEqual(errors, [BlockRange(B1.public_key, B1.sequence_number, B1.sequence_number)]) db.add_block(B2) A1 = TestBlock( key = A, block_type=BlockTypes.TRANSFER, transaction={'amount': 5, 'balance': 0}, linked = B2 ) result, errors = A1.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) db.add_block(A1) # A tries to verify and fails A2 = TestBlock( block_type=BlockTypes.CHECKPOINT, transaction={'balance': 5}, previous=A1, links=G ) result, errors = A2.validate_transaction(db) self.assertEqual(result, ValidationResult.missing) self.assertEqual(errors, [BlockRange(B1.public_key, B1.sequence_number, B1.sequence_number)]) db.add_block(A2) # A adds a rollback block A3 = TestBlock( block_type=BlockTypes.ROLLBACK, transaction={'balance': 0, 'amount': 5, 'transaction_hash': hexlify(A1.hash)}, previous=A2, links=A ) result, errors = A3.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) db.add_block(A3) # A tries to verify and succeeds A4 = TestBlock( block_type=BlockTypes.CHECKPOINT, transaction={'balance': 0}, previous=A3, links=G ) result, errors = A4.validate_transaction(db) self.assertEqual(errors, []) self.assertEqual(result, ValidationResult.valid) db.add_block(A4)