test_verifications.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. from .utils import *
  2. def block_test(proof_of_work_res=True):
  3. """ Immediately runs a test that requires a blockchain. """
  4. def decorator(fn):
  5. def wrapper():
  6. orig_proof = src.proof_of_work.verify_proof_of_work
  7. src.proof_of_work.verify_proof_of_work = lambda b: proof_of_work_res
  8. src.block.verify_proof_of_work = src.proof_of_work.verify_proof_of_work
  9. chain = Blockchain()
  10. try:
  11. fn(chain)
  12. finally:
  13. src.block.verify_proof_of_work = orig_proof
  14. src.proof_of_work.verify_proof_of_work = orig_proof
  15. return wrapper
  16. return decorator
  17. def trans_test(fn):
  18. """ Immediately runs a test that requires a blockchain, and a transaction with private key in that blockchain. """
  19. @block_test()
  20. def wrapper(gen_chain):
  21. key = Signing.generate_private_key()
  22. reward_trans = Transaction([], [TransactionTarget(key, gen_chain.compute_blockreward_next_block())])
  23. chain = extend_blockchain(gen_chain, [reward_trans])
  24. fn(chain, reward_trans)
  25. return wrapper
  26. @trans_test
  27. def test_double_spend1(chain, reward_trans):
  28. trans1 = new_trans(reward_trans)
  29. chain = extend_blockchain(chain, [trans1])
  30. # spending the coin in reward_trans again must fail:
  31. extend_blockchain(chain, [trans1], verify_res=False)
  32. # spending the output of trans1 must work:
  33. assert trans_as_input(trans1) in chain.unspent_coins
  34. @trans_test
  35. def test_double_spend2(chain, reward_trans):
  36. trans1 = new_trans(reward_trans)
  37. trans2 = new_trans(reward_trans)
  38. extend_blockchain(chain, [trans1, trans2], verify_res=False)
  39. @trans_test
  40. def test_double_spend3(chain, reward_trans):
  41. trans1 = Transaction([trans_as_input(reward_trans), trans_as_input(reward_trans)], [])
  42. key = reward_trans.targets[0].recipient_pk
  43. trans1.sign([key, key])
  44. extend_blockchain(chain, [trans1], verify_res=False)
  45. @trans_test
  46. def test_create_money1(chain, reward_trans):
  47. key = reward_trans.targets[0].recipient_pk
  48. # create a transaction where the receiver gets 1 more coin than the sender puts in
  49. target = TransactionTarget(key, reward_trans.targets[0].amount + 1)
  50. trans1 = Transaction([trans_as_input(reward_trans)], [target])
  51. trans1.sign([key])
  52. extend_blockchain(chain, [trans1], verify_res=False)
  53. @trans_test
  54. def test_create_money2(chain, reward_trans):
  55. # create a transaction where we create money by sending a negative amount N to someone
  56. # and the inputs + N to us
  57. key = reward_trans.targets[0].recipient_pk
  58. target1 = TransactionTarget(key, -10)
  59. target2 = TransactionTarget(key, reward_trans.targets[0].amount + 10)
  60. trans1 = Transaction([trans_as_input(reward_trans)], [target1, target2])
  61. trans1.sign([key])
  62. extend_blockchain(chain, [trans1], verify_res=False)
  63. @trans_test
  64. def test_dupl_block_reward(chain, reward_trans):
  65. key = reward_trans.targets[0].recipient_pk
  66. target1 = TransactionTarget(key, 1)
  67. trans1 = Transaction([], [target1], iv=b"1")
  68. trans2 = Transaction([], [target1], iv=b"2")
  69. extend_blockchain(chain, [trans1, trans2], verify_res=False)
  70. @trans_test
  71. def test_negative_block_reward(chain, reward_trans):
  72. key = reward_trans.targets[0].recipient_pk
  73. target1 = TransactionTarget(key, -1)
  74. trans1 = Transaction([], [target1], iv=b"1")
  75. extend_blockchain(chain, [trans1], verify_res=False)
  76. @trans_test
  77. def test_zero_block_reward(chain, reward_trans):
  78. extend_blockchain(chain, [], verify_res=True)
  79. @trans_test
  80. def test_too_large_block_reward(chain, reward_trans):
  81. key = reward_trans.targets[0].recipient_pk
  82. target1 = TransactionTarget(key, chain.compute_blockreward_next_block() + 1)
  83. trans1 = Transaction([], [target1], iv=b"1")
  84. extend_blockchain(chain, [trans1], verify_res=False)
  85. trans2 = new_trans(reward_trans, fee=1)
  86. target2 = TransactionTarget(key, chain.compute_blockreward_next_block() + 2)
  87. trans3 = Transaction([], [target2], iv=b"2")
  88. extend_blockchain(chain, [trans2, trans3], verify_res=False)
  89. @trans_test
  90. def test_max_block_reward(chain, reward_trans):
  91. key = reward_trans.targets[0].recipient_pk
  92. target1 = TransactionTarget(key, chain.compute_blockreward_next_block())
  93. trans1 = Transaction([], [target1], iv=b"1")
  94. extend_blockchain(chain, [trans1], verify_res=True)
  95. trans2 = new_trans(reward_trans, fee=1)
  96. target2 = TransactionTarget(key, chain.compute_blockreward_next_block() + 1)
  97. trans3 = Transaction([], [target2], iv=b"2")
  98. extend_blockchain(chain, [trans2, trans3], verify_res=True)
  99. @trans_test
  100. def test_spend_too_much(chain, reward_trans):
  101. trans = new_trans(reward_trans, fee=-1)
  102. assert trans.targets[0].amount == reward_trans.targets[0].amount + 1
  103. extend_blockchain(chain, [trans], verify_res=False)
  104. @trans_test
  105. def test_spend_unknown_coin(chain, reward_trans):
  106. key = reward_trans.targets[0].recipient_pk
  107. inp1 = TransactionInput(reward_trans.get_hash(), len(reward_trans.targets))
  108. trans1 = Transaction([inp1], [])
  109. trans1.sign([key])
  110. extend_blockchain(chain, [trans1], verify_res=False)
  111. inp2 = TransactionInput(b"invalid", 0)
  112. trans2 = Transaction([inp2], [])
  113. trans2.sign([key])
  114. extend_blockchain(chain, [trans2], verify_res=False)
  115. @trans_test
  116. def test_send_zero(chain, reward_trans):
  117. trans = new_trans(reward_trans, fee=reward_trans.targets[0].amount)
  118. assert trans.targets[0].amount == 0
  119. extend_blockchain(chain, [trans], verify_res=False)
  120. @trans_test
  121. def test_invalid_signature(chain, reward_trans):
  122. trans1 = new_trans(reward_trans, fee=0)
  123. trans2 = new_trans(reward_trans, fee=1)
  124. trans1.signatures, trans2.signatures = trans2.signatures, trans1.signatures
  125. extend_blockchain(chain, [trans1], verify_res=False)
  126. extend_blockchain(chain, [trans2], verify_res=False)
  127. trans3 = Transaction(trans1.inputs, trans1.targets, signatures=trans1.signatures+trans2.signatures)
  128. extend_blockchain(chain, [trans3], verify_res=False)
  129. trans4 = Transaction(trans1.inputs, trans1.targets, signatures=[])
  130. extend_blockchain(chain, [trans4], verify_res=False)
  131. # too few signatures:
  132. key = reward_trans.targets[0].recipient_pk
  133. target1 = TransactionTarget(key, 1)
  134. target2 = TransactionTarget(key, 1)
  135. trans5 = Transaction(trans1.inputs, [target1, target2])
  136. trans5.sign([key])
  137. extend_blockchain(chain, [trans5], verify_res=True)
  138. input1 = TransactionInput(trans5.get_hash(), 0)
  139. input2 = TransactionInput(trans5.get_hash(), 1)
  140. trans6 = Transaction([input1, input2], [])
  141. trans6.sign([key, key])
  142. trans6.signatures.pop()
  143. extend_blockchain(chain, [trans6], verify_res=False)
  144. @block_test(proof_of_work_res=False)
  145. def test_invalid_proof_of_work(chain):
  146. block = Block.create(chain, [])
  147. assert chain.try_append(block) is None
  148. @block_test()
  149. def test_invalid_prev_hash(chain):
  150. block = create_block(chain, prev_block_hash="0001020304")
  151. assert chain.try_append(block) is None
  152. @block_test()
  153. def test_invalid_merkle_root_hash(chain):
  154. block = create_block(chain, merkle_root_hash="0001020304")
  155. assert chain.try_append(block) is None
  156. @block_test()
  157. def test_monotonic_time(chain):
  158. block = create_block(chain, time="1900-01-01T00:00:00.000000 UTC")
  159. assert chain.try_append(block) is None
  160. @block_test()
  161. def test_future_time(chain):
  162. block = create_block(chain, time="2900-01-01T00:00:00.000000 UTC")
  163. assert chain.try_append(block) is None
  164. @block_test()
  165. def test_invalid_height(chain):
  166. block = create_block(chain, height=-1)
  167. assert chain.try_append(block) is None
  168. block = create_block(chain, height=chain.head.height)
  169. assert chain.try_append(block) is None
  170. block = create_block(chain, height=chain.head.height ** 42)
  171. assert chain.try_append(block) is None
  172. block = create_block(chain, height=chain.head.height ** 42)
  173. assert chain.try_append(block) is None
  174. @block_test()
  175. def test_invalid_difficulty(chain):
  176. block = create_block(chain, difficulty=-1)
  177. assert chain.try_append(block) is None
  178. block = create_block(chain, difficulty=chain.head.difficulty + 1)
  179. assert chain.try_append(block) is None
  180. block = create_block(chain, difficulty=chain.head.difficulty - 1)
  181. assert chain.try_append(block) is None
  182. block = create_block(chain, difficulty=chain.head.difficulty ** 42)
  183. assert chain.try_append(block) is None
  184. @block_test()
  185. def test_invalid_height_difficulty(chain):
  186. block = create_block(chain, height=chain.head.height - 1, difficulty=-1)
  187. assert chain.try_append(block) is None
  188. block = create_block(chain, height=chain.head.height, difficulty=0)
  189. assert chain.try_append(block) is None
  190. block = create_block(chain, height=chain.head.height + 1, difficulty=1)
  191. assert chain.try_append(block) is None
  192. block = create_block(chain, height=chain.head.height * 42, difficulty=chain.head.height * 41)
  193. assert chain.try_append(block) is None
  194. block = create_block(chain, height=chain.head.height + chain.head.difficulty + 1,
  195. difficulty=chain.head.difficulty + 1)
  196. assert chain.try_append(block) is None
  197. block = create_block(chain, height=chain.head.height + chain.head.difficulty - 1,
  198. difficulty=chain.head.difficulty - 1)
  199. assert chain.try_append(block) is None