def test_invalid_proofs_score_too_large(): testdb = create_reward_test_blockchain_database() chain = TestnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) required_number_of_proofs_for_reward_type_2_proof = chain.get_consensus_db( timestamp=Timestamp(int( time.time()))).required_number_of_proofs_for_reward_type_2_proof node_staking_scores = [] # First score/proof has a score too large current_private_key = private_keys[1] node_staking_score = NodeStakingScore( recipient_node_wallet_address=private_keys[0].public_key. to_canonical_address(), score=int(1000001), since_block_number=0, timestamp=int(time.time()), head_hash_of_sender_chain=chain.chaindb.get_canonical_head_hash( current_private_key.public_key.to_canonical_address()), v=0, r=0, s=0, ) signed_node_staking_score = node_staking_score.get_signed( current_private_key, TESTNET_NETWORK_ID) node_staking_scores.append(signed_node_staking_score) score = 1000000 for i in range(2, 10): # Second score/proof is from instance 1 current_private_key = private_keys[i] node_staking_score = NodeStakingScore( recipient_node_wallet_address=private_keys[0].public_key. to_canonical_address(), score=int(score - i), since_block_number=0, timestamp=int(time.time()), head_hash_of_sender_chain=chain.chaindb.get_canonical_head_hash( current_private_key.public_key.to_canonical_address()), v=0, r=0, s=0, ) signed_node_staking_score = node_staking_score.get_signed( current_private_key, TESTNET_NETWORK_ID) node_staking_scores.append(signed_node_staking_score) # Now we try to import the reward block with instance 0 reward_chain = TestnetChain( testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) with pytest.raises(ValidationError): reward_chain.import_current_queue_block_with_reward( node_staking_scores)
def test_invalid_proofs_timestamp_in_past(): testdb = create_reward_test_blockchain_database() chain = MainnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) min_time_between_blocks = chain.get_vm(timestamp=Timestamp(int(time.time()))).min_time_between_blocks tx_list = [[private_keys[1], private_keys[0], to_wei(1, 'ether'), int(int(time.time())-min_time_between_blocks*10)]] add_transactions_to_blockchain_db(testdb, tx_list) chain = MainnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) required_number_of_proofs_for_reward_type_2_proof = chain.get_consensus_db(timestamp=Timestamp(int(time.time()))).required_number_of_proofs_for_reward_type_2_proof node_staking_scores = [] # First score/proof with timestamp far in future current_private_key = private_keys[1] node_staking_score = NodeStakingScore( recipient_node_wallet_address=private_keys[0].public_key.to_canonical_address(), score=int(1000000), since_block_number=0, timestamp=int(time.time())-60*10, head_hash_of_sender_chain=chain.chaindb.get_canonical_head_hash( current_private_key.public_key.to_canonical_address()), v=0, r=0, s=0, ) signed_node_staking_score = node_staking_score.get_signed(current_private_key, MAINNET_NETWORK_ID) node_staking_scores.append(signed_node_staking_score) score = 100000 for i in range(2, 10): # Second score/proof is from instance 1 current_private_key = private_keys[i] node_staking_score = NodeStakingScore( recipient_node_wallet_address=private_keys[0].public_key.to_canonical_address(), score=int(score-i), since_block_number=1, timestamp=int(time.time()), head_hash_of_sender_chain=chain.chaindb.get_canonical_head_hash( current_private_key.public_key.to_canonical_address()), v=0, r=0, s=0, ) signed_node_staking_score = node_staking_score.get_signed(current_private_key, MAINNET_NETWORK_ID) node_staking_scores.append(signed_node_staking_score) # Now we try to import the reward block with instance 0 reward_chain = MainnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) with pytest.raises(ValidationError): reward_chain.import_current_queue_block_with_reward(node_staking_scores)
def get_signed_peer_score( self, private_key: PrivateKey, network_id: int, peer_wallet_address: Address, after_block_number: BlockNumber = None, ) -> NodeStakingScore: this_node_wallet_address = private_key.public_key.to_canonical_address( ) if after_block_number is None: after_block_number = self.chaindb.get_latest_reward_block_number( peer_wallet_address) peer_node_health = self._get_peer_node_health(peer_wallet_address, after_block_number) # fields = [ # ('recipient_node_wallet_address', address), # ('score', f_big_endian_int), # ('since_block_number', f_big_endian_int), # ('timestamp', f_big_endian_int), # ('v', f_big_endian_int), # ('r', f_big_endian_int), # ('s', f_big_endian_int), # ] #need to get the time since the block. try: header = self.chaindb.get_canonical_block_header_by_number( after_block_number, peer_wallet_address) except HeaderNotFound: raise ValueError( "Cannot find previous block that is supposed to contain a stake reward" ) since_timestamp = header.timestamp time_since_last_specified_block = int(time.time()) - since_timestamp score = self.calculate_node_staking_score( peer_node_health.requests_sent, peer_node_health.failed_requests, peer_node_health.average_response_time, time_since_last_specified_block) head_hash_of_local_chain = self.chaindb.get_canonical_head_hash( this_node_wallet_address) node_staking_score = NodeStakingScore(peer_wallet_address, score, after_block_number, int(time.time()), head_hash_of_local_chain, v=0, r=0, s=0) signed_node_staking_score = node_staking_score.get_signed( private_key, network_id) return signed_node_staking_score
def create_dev_test_random_blockchain_db_with_reward_blocks(base_db = None, num_iterations = 5): # initialize db if base_db == None: base_db = MemoryDB() create_dev_test_random_blockchain_database(base_db, timestamp = 'genesis') node_1 = TestnetChain(base_db, TESTNET_GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), TESTNET_GENESIS_PRIVATE_KEY) MIN_TIME_BETWEEN_BLOCKS = node_1.get_vm(timestamp = Timestamp(int(time.time()))).min_time_between_blocks chain_head_hashes = node_1.chain_head_db.get_head_block_hashes_list() last_block_timestamp = 0 for head_hash in chain_head_hashes: header = node_1.chaindb.get_block_header_by_hash(head_hash) if header.timestamp > last_block_timestamp: last_block_timestamp = header.timestamp private_keys_dict = {} for random_private_key in random_private_keys: priv_key = keys.PrivateKey(random_private_key) private_keys_dict[priv_key.public_key.to_address()] = priv_key private_keys_dict[TESTNET_GENESIS_PRIVATE_KEY.public_key.to_address()] = TESTNET_GENESIS_PRIVATE_KEY for i in range(num_iterations): # random_int = random.randint(0,len(private_keys_dict)-1) # numbers = [x in range(0, len(private_keys_dict)-1) if x != random_int] # random_int = random.choice(numbers) if i == 0: numbers = [x for x in range(0, len(private_keys_dict) - 1)] random_int = random.choice(numbers) privkey = TESTNET_GENESIS_PRIVATE_KEY receiver_privkey = private_keys_dict[list(private_keys_dict.keys())[random_int]] else: numbers = [x for x in range(0, len(private_keys_dict) - 1) if x != random_int] random_int = random.choice(numbers) privkey = receiver_privkey receiver_privkey = private_keys_dict[list(private_keys_dict.keys())[random_int]] tx_timestamp = last_block_timestamp + MIN_TIME_BETWEEN_BLOCKS+2 tx_list = [[privkey, receiver_privkey, 10000000*10**18-i*100000*10**18-random.randint(0,1000), tx_timestamp]] add_transactions_to_blockchain_db(base_db, tx_list) node_1 = TestnetChain(base_db, privkey.public_key.to_canonical_address(), privkey) chain_head_hashes = node_1.chain_head_db.get_head_block_hashes_list() reward_block_time = tx_timestamp + node_1.get_vm(timestamp = tx_timestamp).consensus_db.min_time_between_reward_blocks+ MIN_TIME_BETWEEN_BLOCKS+2+node_1.get_vm(timestamp = tx_timestamp).consensus_db.coin_mature_time_for_staking # print('BBBBBBB') # print(node_1.get_vm(timestamp=tx_timestamp).state.account_db.get_balance(receiver_privkey.public_key.to_canonical_address())) # print(node_1.chaindb.get_mature_stake(receiver_privkey.public_key.to_canonical_address(), node_1.get_consensus_db(timestamp=tx_timestamp).coin_mature_time_for_staking, reward_block_time)) node_staking_scores = [] for head_hash in chain_head_hashes: address = node_1.chaindb.get_chain_wallet_address_for_block_hash(head_hash) if not (address == privkey.public_key.to_canonical_address()): after_block_number = node_1.chaindb.get_latest_reward_block_number(privkey.public_key.to_canonical_address()) node_staking_score = NodeStakingScore(privkey.public_key.to_canonical_address(), 1, after_block_number, reward_block_time, head_hash, v=0, r=0, s=0) signed_node_staking_score = node_staking_score.get_signed(private_keys_dict[encode_hex(address)], node_1.network_id) node_staking_scores.append(signed_node_staking_score) if len(node_staking_scores) >= node_1.get_consensus_db(timestamp = tx_timestamp).required_number_of_proofs_for_reward_type_2_proof: # print('AAAAAAAAAAAA') # print(len(node_staking_scores)) # print(node_1.get_consensus_db(timestamp = tx_timestamp).required_number_of_proofs_for_reward_type_2_proof) reward_bundle = node_1.get_consensus_db(timestamp=tx_timestamp).create_reward_bundle_for_block(privkey.public_key.to_canonical_address(), node_staking_scores, reward_block_time) valid_block = create_valid_block_at_timestamp(base_db, privkey, reward_bundle = reward_bundle, timestamp = reward_block_time) assert(valid_block.header.timestamp == reward_block_time) node_1.import_block(valid_block) last_block_timestamp = reward_block_time return base_db
def test_break_chronological_consistency_1(): testdb = create_reward_test_blockchain_database() chain = MainnetChain(testdb, private_keys[1].public_key.to_canonical_address(), private_keys[1]) tx_nonce = chain.get_current_queue_block_nonce() tx = chain.create_and_sign_transaction(nonce = tx_nonce, gas_price=to_wei(1, 'gwei'), gas=GAS_TX, to=private_keys[0].public_key.to_canonical_address(), value=1, data=b"", v=0, r=0, s=0 ) new_block_to_import = create_valid_block_at_timestamp(testdb, private_keys[1], transactions=[tx], receive_transactions=None, reward_bundle=None, timestamp=int(time.time()-1)) chain = MainnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) node_staking_scores = [] score = 100000 for i in range(1, 10): # Second score/proof is from instance 1 current_private_key = private_keys[i] node_staking_score = NodeStakingScore( recipient_node_wallet_address=private_keys[0].public_key.to_canonical_address(), score=int(score-i), since_block_number=0, timestamp=int(time.time()), head_hash_of_sender_chain=chain.chaindb.get_canonical_head_hash( current_private_key.public_key.to_canonical_address()), v=0, r=0, s=0, ) signed_node_staking_score = node_staking_score.get_signed(current_private_key, MAINNET_NETWORK_ID) node_staking_scores.append(signed_node_staking_score) # Now we try to import the reward block with instance 0 reward_chain = MainnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) reward_block = reward_chain.import_current_queue_block_with_reward(node_staking_scores) print("reward block timestamp {}".format(reward_block.header.timestamp)) for proof in reward_block.reward_bundle.reward_type_2.proof: print(encode_hex(proof.sender)) for i in range(1, 10): if proof.sender == private_keys[i].public_key.to_canonical_address(): print("proof from {}".format(i)) print("new_block_to_import timestamp {}".format(new_block_to_import.header.timestamp)) print("new_block_to_import chain address {}".format(encode_hex(new_block_to_import.header.chain_address))) # Now we import a block on private key 1 with a timestamp set to 10 seconds ago chain = MainnetChain(testdb, private_keys[1].public_key.to_canonical_address(), private_keys[1]) with pytest.raises(ReplacingBlocksNotAllowed): chain.import_block(new_block_to_import, allow_replacement=False) # test_break_chronological_consistency_1() # exit()
def test_invalid_proofs_not_enough_stake(): testdb = MemoryDB() chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) coin_mature_time = chain.get_vm(timestamp=Timestamp(int(time.time()))).consensus_db.coin_mature_time_for_staking min_time_between_blocks = chain.get_vm(timestamp=Timestamp(int(time.time()))).min_time_between_blocks now = int(time.time()) start = now - max((coin_mature_time * 2), (min_time_between_blocks * 20)) key_balance_dict = { private_keys[0]: (to_wei(1, 'ether'), start), private_keys[1]: (to_wei(1, 'ether'), start + min_time_between_blocks * 1), private_keys[2]: (to_wei(1, 'ether'), start + min_time_between_blocks * 2), private_keys[3]: (to_wei(1, 'ether'), start + min_time_between_blocks * 3), private_keys[4]: (to_wei(1, 'ether'), start + min_time_between_blocks * 4), private_keys[5]: (to_wei(1, 'ether'), start + min_time_between_blocks * 5), private_keys[6]: (to_wei(1, 'ether'), start + min_time_between_blocks * 6), private_keys[7]: (to_wei(1, 'ether'), start + min_time_between_blocks * 7), private_keys[8]: (to_wei(1, 'ether'), start + min_time_between_blocks * 8), private_keys[9]: (to_wei(1, 'ether'), now - coin_mature_time + 1), # immature } create_dev_fixed_blockchain_database(testdb, key_balance_dict) chain = MainnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) node_staking_scores = [] # First score/proof with timestamp far in future current_private_key = private_keys[1] node_staking_score = NodeStakingScore( recipient_node_wallet_address=private_keys[0].public_key.to_canonical_address(), score=int(1000000), since_block_number=0, timestamp=int(time.time())-60*10, head_hash_of_sender_chain=chain.chaindb.get_canonical_head_hash( current_private_key.public_key.to_canonical_address()), v=0, r=0, s=0, ) signed_node_staking_score = node_staking_score.get_signed(current_private_key, MAINNET_NETWORK_ID) node_staking_scores.append(signed_node_staking_score) score = 100000 for i in range(2, 10): # Second score/proof is from instance 1 current_private_key = private_keys[i] node_staking_score = NodeStakingScore( recipient_node_wallet_address=private_keys[0].public_key.to_canonical_address(), score=int(score-i), since_block_number=1, timestamp=int(time.time()), head_hash_of_sender_chain=chain.chaindb.get_canonical_head_hash( current_private_key.public_key.to_canonical_address()), v=0, r=0, s=0, ) signed_node_staking_score = node_staking_score.get_signed(current_private_key, MAINNET_NETWORK_ID) node_staking_scores.append(signed_node_staking_score) # Now we try to import the reward block with instance 0 reward_chain = MainnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) with pytest.raises(NotEnoughProofsOrStakeForRewardType2Proof): reward_chain.import_current_queue_block_with_reward(node_staking_scores)
def _test_block_rewards_system(): #The genesis chain will be adding a reward block. We need to generate fake NodeStakingScores from a bunch of other #nodes # testdb = LevelDB('/home/tommy/.local/share/helios/instance_test/mainnet/chain/full/') # testdb = JournalDB(testdb) testdb = create_reward_test_blockchain_database() chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) coin_mature_time = chain.get_vm(timestamp=Timestamp(int(time.time()))).consensus_db.coin_mature_time_for_staking min_time_between_blocks = chain.get_vm(timestamp=Timestamp(int(time.time()))).min_time_between_blocks # now = int(time.time()) # start = now - max((coin_mature_time * 2), (min_time_between_blocks*20)) # key_balance_dict = { # private_keys[0]: (to_wei(10, 'ether'), start), # private_keys[1]: (to_wei(200, 'ether'), start + min_time_between_blocks * 1), # private_keys[2]: (to_wei(340, 'ether'), start + min_time_between_blocks * 2), # private_keys[3]: (to_wei(1000, 'ether'), start + min_time_between_blocks * 3), # private_keys[4]: (to_wei(1400, 'ether'), start + min_time_between_blocks * 4), # private_keys[5]: (to_wei(2400, 'ether'), start + min_time_between_blocks * 5), # private_keys[6]: (to_wei(3000, 'ether'), start + min_time_between_blocks * 6), # private_keys[7]: (to_wei(4000, 'ether'), start + min_time_between_blocks * 7), # private_keys[8]: (to_wei(1000, 'ether'), start + min_time_between_blocks * 8), # private_keys[9]: (to_wei(10000, 'ether'), now-coin_mature_time+1),# immature # } # create_dev_fixed_blockchain_database(testdb, key_balance_dict) chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) # class NodeStakingScore(rlp.Serializable, metaclass=ABCMeta): # fields = [ # ('recipient_node_wallet_address', address), # ('score', f_big_endian_int), # ('since_block_number', f_big_endian_int), # ('timestamp', f_big_endian_int), # ('v', big_endian_int), # ('r', big_endian_int), # ('s', big_endian_int), # ] node_staking_scores = [] score = 1000000 for private_key in private_keys: node_staking_score = NodeStakingScore(recipient_node_wallet_address = GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), score = int(score), since_block_number = 0, timestamp = int(time.time()), head_hash_of_sender_chain = chain.chaindb.get_canonical_head_hash(private_key.public_key.to_canonical_address()), v = 0, r = 0, s = 0, ) signed_node_staking_score = node_staking_score.get_signed(private_key,MAINNET_NETWORK_ID) node_staking_scores.append(signed_node_staking_score) score = score/5 chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) node_staking_scores.sort(key=lambda x: -1* x.score) for node_staking_score in node_staking_scores: node_staking_score.validate() print(node_staking_score.is_signature_valid) print(node_staking_score.sender) print(node_staking_score.score, chain.get_mature_stake(node_staking_score.sender, node_staking_score.timestamp)) reward_bundle = chain.get_consensus_db().create_reward_bundle_for_block(GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), node_staking_scores, at_timestamp = int(time.time())) chain.get_consensus_db().validate_reward_bundle(reward_bundle, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), int(time.time())) print('AAAAAAAAAAA') print(reward_bundle.reward_type_1.amount) print(reward_bundle.reward_type_2.amount) print(reward_bundle.reward_type_2.proof[0].score) initial_balance = chain.get_vm().state.account_db.get_balance(GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) print("balance before reward = ", initial_balance) chain.import_current_queue_block_with_reward(reward_bundle.reward_type_2.proof) final_balance = chain.get_vm().state.account_db.get_balance(GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) print("balance after reward = ",final_balance) assert((reward_bundle.reward_type_1.amount + reward_bundle.reward_type_2.amount) == (final_balance- initial_balance)) print("waiting {} seconds before importing the next block".format(min_time_between_blocks)) time.sleep(min_time_between_blocks) proof_chain = MainnetChain(testdb, private_keys[1].public_key.to_canonical_address(), private_keys[1]) mature_stake = proof_chain.get_mature_stake() print("proof chain mature stake") print(mature_stake) staking_score = proof_chain.get_signed_peer_score_string_private_key(private_keys[1].to_bytes(), private_keys[0].public_key.to_canonical_address()) staking_score = staking_score.copy(score=1532) staking_score = staking_score.get_signed(private_keys[1], proof_chain.network_id) print('staking score') print(staking_score.score) # fields = [ # ('recipient_node_wallet_address', address), # ('score', f_big_endian_int), # a score out of 1,000,000 # ('since_block_number', f_big_endian_int), # ('timestamp', f_big_endian_int), # ('head_hash_of_sender_chain', hash32), # ('v', big_endian_int), # ('r', big_endian_int), # ('s', big_endian_int), # ] # reward_chain = MainnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) reward_bundle = reward_chain.get_consensus_db().create_reward_bundle_for_block(private_keys[0].public_key.to_canonical_address(), [staking_score],at_timestamp=Timestamp(int(time.time()))) print("reward type 2 amount") print(reward_bundle.reward_type_2.amount) print("reward type 2 proof") print(reward_bundle.reward_type_2.proof) reward_chain.import_current_queue_block_with_reward([staking_score]) # todo: this will fail if the reward block time is too long. Need to manually set it to a small number for the test... or manually make the blocks older? print("waiting {} seconds before importing the next block".format(min_time_between_blocks)) time.sleep(min_time_between_blocks) proof_chain = MainnetChain(testdb, private_keys[1].public_key.to_canonical_address(), private_keys[1]) mature_stake = proof_chain.get_mature_stake() print("proof chain mature stake") print(mature_stake) staking_score = proof_chain.get_signed_peer_score_string_private_key(private_keys[1].to_bytes(), private_keys[ 0].public_key.to_canonical_address()) staking_score = staking_score.copy(score=1000000) staking_score = staking_score.get_signed(private_keys[1], proof_chain.network_id) print('staking score') print(staking_score.score) # fields = [ # ('recipient_node_wallet_address', address), # ('score', f_big_endian_int), # a score out of 1,000,000 # ('since_block_number', f_big_endian_int), # ('timestamp', f_big_endian_int), # ('head_hash_of_sender_chain', hash32), # ('v', big_endian_int), # ('r', big_endian_int), # ('s', big_endian_int), # ] # reward_chain = MainnetChain(testdb, private_keys[0].public_key.to_canonical_address(), private_keys[0]) reward_bundle = reward_chain.get_consensus_db().create_reward_bundle_for_block( private_keys[0].public_key.to_canonical_address(), [staking_score], at_timestamp=Timestamp(int(time.time()))) print("reward type 2 amount") print(reward_bundle.reward_type_2.amount) print("reward type 2 proof") print(reward_bundle.reward_type_2.proof) reward_chain.import_current_queue_block_with_reward([staking_score])