def add_transactions_to_blockchain_db(base_db, tx_list: List):
    # sort by time
    tx_list.sort(key=lambda x: x[3])

    for tx_key in tx_list:
        sender_priv_key = tx_key[0]
        receive_priv_key = tx_key[1]
        amount = tx_key[2]
        tx_timestamp = int(tx_key[3])

        if len(tx_key) > 4:
            gas_price = to_wei(tx_key[4], 'gwei')
        else:
            gas_price = to_wei(1, 'gwei')

        total_gas = gas_price
        sender_chain = MainnetChain(base_db, sender_priv_key.public_key.to_canonical_address(), sender_priv_key)
        dummy_sender_chain = MainnetChain(JournalDB(base_db), sender_priv_key.public_key.to_canonical_address(),
                                          sender_priv_key)

        dummy_sender_chain.create_and_sign_transaction_for_queue_block(
            gas_price=gas_price,
            gas=GAS_TX,
            to=receive_priv_key.public_key.to_canonical_address(),
            value=amount,
            data=b"",
            v=0,
            r=0,
            s=0
        )

        # import the block into the dummy chain to complete it and make sure it is valid
        imported_block = dummy_sender_chain.import_current_queue_block()

        # altering block timestamp and importing again
        timestamp_modified_imported_block = imported_block.copy(
            header=imported_block.header.copy(timestamp=tx_timestamp).get_signed(sender_priv_key,
                                                                                 dummy_sender_chain.network_id))
        sender_chain.import_block(timestamp_modified_imported_block, allow_unprocessed=False)

        # then receive the transactions

        dummy_receiver_chain = MainnetChain(JournalDB(base_db), receive_priv_key.public_key.to_canonical_address(),
                                            receive_priv_key)
        dummy_receiver_chain.populate_queue_block_with_receive_tx()
        imported_block = dummy_receiver_chain.import_current_queue_block()

        # altering block timestamp and importing again
        timestamp_modified_imported_block = imported_block.copy(
            header=imported_block.header.copy(timestamp=tx_timestamp).get_signed(receive_priv_key,
                                                                                  dummy_receiver_chain.network_id))
        # print('XXXXXXXXXX')
        # print(tx_timestamp)
        receiver_chain = MainnetChain(base_db, receive_priv_key.public_key.to_canonical_address(), receive_priv_key)
        receiver_chain.import_block(timestamp_modified_imported_block, allow_unprocessed=False)
Exemple #2
0
def debug_test_1():
    testdb = LevelDB("/home/tommy/.local/share/helios/mainnet/chain/full/")

    testdb = JournalDB(testdb)
    testdb = ReadOnlyDB(testdb)

    chain = MainnetChain(testdb,
                         private_keys[0].public_key.to_canonical_address(),
                         private_keys[0])

    block = chain.get_block_by_hash(
        decode_hex(
            '0x6a8d49885e5f07ea66f722e4ec9ba9630a86f1189257317461196726bee7ea0c'
        ))

    new_chain = chain.get_blocks_on_chain(
        0, 3, decode_hex('0x1d1a2266a15CcB2e70baeB4b75b2c59Da95498ac'))

    print('blocks on chain')
    for cur_block in new_chain:
        print(encode_hex(cur_block.header.hash))

    print()

    newest_root_hash = chain.chain_head_db.get_historical_root_hashes()[-1][1]
    chain.chain_head_db.root_hash = newest_root_hash
    chain_head_hash = chain.chain_head_db.get_chain_head_hash(
        decode_hex('0x1d1a2266a15CcB2e70baeB4b75b2c59Da95498ac'))
    print("chain_head_hash {}".format(encode_hex(chain_head_hash)))

    #
    # now lets delete all but the first block
    #
    print("Deleting all blocks but first")
    chain = MainnetChain(testdb,
                         private_keys[0].public_key.to_canonical_address(),
                         private_keys[0])
    chain.purge_block_and_all_children_and_set_parent_as_chain_head(
        block.header, save_block_head_hash_timestamp=True)

    newest_root_hash = chain.chain_head_db.get_historical_root_hashes()[-1][1]
    chain.chain_head_db.root_hash = newest_root_hash
    chain_head_hash = chain.chain_head_db.get_chain_head_hash(
        decode_hex('0x1d1a2266a15CcB2e70baeB4b75b2c59Da95498ac'))
    print("chain_head_hash {}".format(encode_hex(chain_head_hash)))

    #
    # Now lets import the second block again
    #

    print("Importing second block")
    chain.import_block(
        block,
        allow_replacement=False,
        ensure_block_unchanged=True,
    )

    newest_root_hash = chain.chain_head_db.get_historical_root_hashes()[-1][1]
    chain.chain_head_db.root_hash = newest_root_hash
    chain_head_hash = chain.chain_head_db.get_chain_head_hash(
        decode_hex('0x1d1a2266a15CcB2e70baeB4b75b2c59Da95498ac'))
    print("chain_head_hash {}".format(encode_hex(chain_head_hash)))
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 create_dev_fixed_blockchain_database(base_db, key_balance_dict, use_real_genesis = False):
    logger.debug("generating test fixed blockchain db")

    earliest_timestamp = int(time.time())
    required_total_supply = 0
    for balance_timestamp in key_balance_dict.values():
        required_total_supply += balance_timestamp[0]
        if balance_timestamp[1] < earliest_timestamp:
            earliest_timestamp = balance_timestamp[1]

    required_total_supply = required_total_supply*2

    #initialize db
    if use_real_genesis:
        sender_chain = import_genesis_block(base_db)
    else:
        genesis_params, genesis_state = create_new_genesis_params_and_state(GENESIS_PRIVATE_KEY, required_total_supply, earliest_timestamp - 100000)
        sender_chain = MainnetChain.from_genesis(base_db, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), genesis_params, genesis_state)

    sender_chain.chaindb.initialize_historical_minimum_gas_price_at_genesis(min_gas_price=1, net_tpc_cap=5)

    prev_timestamp = 0
    for priv_key, balance_timestamp in key_balance_dict.items():
        sender_chain = MainnetChain(base_db, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY)

        dummy_sender_chain = MainnetChain(JournalDB(base_db), GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY)

        balance = balance_timestamp[0]
        timestamp = balance_timestamp[1]
        if timestamp < prev_timestamp:
            raise ValueError("timestamps must be in ascending order")

        receiver_privkey = priv_key

        dummy_sender_chain.create_and_sign_transaction_for_queue_block(
                gas_price=0x01,
                gas=0x0c3500,
                to=receiver_privkey.public_key.to_canonical_address(),
                value=balance,
                data=b"",
                v=0,
                r=0,
                s=0
                )



        # import the block into the dummy chain to complete it and make sure it is valid
        imported_block = dummy_sender_chain.import_current_queue_block()

        # altering block timestamp and importing again
        timestamp_modified_imported_block = imported_block.copy(header = imported_block.header.copy(timestamp = timestamp).get_signed(GENESIS_PRIVATE_KEY,dummy_sender_chain.network_id))
        sender_chain.import_block(timestamp_modified_imported_block, allow_unprocessed = False)

        #logger.debug("Receiving ")

        #then receive the transactions
        receiver_chain = MainnetChain(base_db, receiver_privkey.public_key.to_canonical_address(), receiver_privkey)
        dummy_receiver_chain = MainnetChain(JournalDB(base_db), receiver_privkey.public_key.to_canonical_address(), receiver_privkey)
        dummy_receiver_chain.populate_queue_block_with_receive_tx()
        imported_block = dummy_receiver_chain.import_current_queue_block()

        # altering block timestamp and importing again
        timestamp_modified_imported_block = imported_block.copy(header=imported_block.header.copy(timestamp=timestamp).get_signed(receiver_privkey, dummy_receiver_chain.network_id))
        receiver_chain.import_block(timestamp_modified_imported_block, allow_unprocessed=False)


    logger.debug("finished creating fixed blockchain")
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 = MainnetChain(base_db, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), 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[GENESIS_PRIVATE_KEY.public_key.to_address()] = 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 = 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 = MainnetChain(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