def test_transaction_hashable_fail():
    test_time = int(time.time())
    block_time = int(time.time())
    transaction_1 = Transaction('block_hash_test', '', 'to_steven_test', 'from_matt_test', 1, test_time)
    transaction_2 = Transaction('block_hash_test2', '', 'to_matt_test', 'from_steven_test', 1, test_time)
    block = Block('_hash_test', '','', 'LAST_BLOCK', 0, [
        transaction_1,
        transaction_2
    ], [], [], [], [], [], block_time)
    actual = block.get_hashable()
    expected = {
        'owner': '',
        'prev_block': 'LAST_BLOCK',
        'height': 0,
        'signature': '',
        'transactions': [
            transaction_1.get_sendable(),
            transaction_2.get_sendable()
        ],
        'pos_transactions': [],
        'contract_transactions': [],
        'contracts': [],
        'signed_contracts': [],
        'terminated_contracts': [],
        'timestamp': block_time
    }
    assert actual == expected
def test_store_same_hash():
    b = Block('block_service_test_1', '', '', 'LAST_BLOCK', 0, [], [], [], [],
              [], [])

    bs = BlockService()

    bs.store_block(b)

    new_b = bs.find_by_hash('block_service_test_1')

    assert b.get_sendable() != new_b.get_sendable()
    r = redis.Redis()
    r.flushdb()
def test_pos_author():
    expected = 'c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34'
    r = redis.Redis()
    r.flushdb()
    genesis_block = {
        "height": 0,
        "prev_block": "",
        "_hash": "036850bec30839508bf16badc1efc5c0a31eb82f8b23c524c7ea8cd3d0c8b81f",
        "terminated_contracts": [],
        "signed_contracts": [],
        "contracts": [],
        "pos_transactions": [{
            "from_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "82b2704e380f4bc55c214d44f4cdd698ec3ed5471882d0ae67d80462f13434f5",
            "amount": "100.00000000",
            "signature": "2b6f4ad89868f8a820f682fb580a20b3383e9889b50736a66c8ed441ac4ebb29b7f32d6efe929b05d66de7ac0e20d0ea471f7a1e482f505f2f0df3221d720ba4"
        }],
        "contract_transactions": [],
        "timestamp": 1520135639,
        "owner": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
        "transactions": [{
            "to_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "f54029850ab8ffc3d3f1b210bee0008f1b42aa45e267925f42b80ed9eedb1c20",
            "amount": "1.00000000",
            "from_addr": "",
            "signature": "36a0131c4087dae1d0909baf5ea1b35c9955db7e775646df40d35ad6469469b21439e08263ab7a2fa03f3285fb13ce1b80b399bb6f254694e3f36b9ed5fa6a98"
        }, {
            "to_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "ac32ce4867f65d575d95109b59e713f180541cd5c76ca93dad7cea210ebfa26c",
            "amount": "10.00000000",
            "from_addr": "",
            "signature": "83abc47ca9ad48e91b63d6d4bba28786abfc7345f29f02dbf1c90b4e66f91413cf9a081314095d4bf30d508b9781d035a5816f13ea0c1f1d6b6dd59665697b15"
        }, {
            "to_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "e1e65c22699599507d2621b84a39b02ca525e5d3881c583d4d96cffdf3ceced7",
            "amount": "100.00000000",
            "from_addr": "",
            "signature": "998d03e220b28ad99b2b6d7a00cc1a06443ceea8a3a96acc896c6d8953b44d78f58a6cfbf699d5b4ed35f062cb05674d2f10718ecf44d07a300a781c21734220"
        }, {
            "to_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "b3cf3fba2d1b5e3ca6fee0b5d22a1b81f038ffd9e825119f1a7226e3e10a61ee",
            "amount": "1000.00000000",
            "from_addr": "",
            "signature": "556474088e1f4c75f24cb72db8b0be78134d10d0323c40569207baef1172c43b96596573a446389d2330d781109b76da8725d2ef29876cdd4a198fafc9cbf50f"
        }],
        "signature": "3a3a88935574c820fa70a2408f594585d03988df1980f6c0129b84ee129c322c683de1a7f8be6087d468abbbeb32f2a49eb0ac0c64a9b8de57d43a480ebf4dfc"
    }
    block = Block.from_dict(genesis_block)
    dal_block_service = DalBlockService()
    dal_block_service.store_block(block)
    actual = POSService.get_next_block_author(block)
    print(actual)
    assert actual == expected
def test_hashable_fail():
    test_time = int(time.time())
    block = Block('block_hash_test', '', '', 'LAST_BLOCK', 0, [], [], [], [], [], [], test_time)
    actual = block.get_hashable()
    not_expected = {
        'owner': '',
        'prev_block': 'LAST_BLOCK',
        'height': 1,
        'signature': '',
        'transactions': [],
        'pos_transactions': [],
        'contract_transactions': [],
        'contracts': [],
        'signed_contracts': [],
        'terminated_contracts': [],
        'timestamp': test_time
    }
    assert actual != not_expected
def test_sendable():
    test_time = int(time.time())
    block = Block('block_send_test', '', '', 'LAST_BLOCK', 0, [], [], [], [], [], [], test_time)
    actual = block.get_sendable()
    expected = {
        'owner': '',
        'prev_block': 'LAST_BLOCK',
        'height': 0,
        'signature': '',
        'transactions': [],
        'pos_transactions': [],
        'contract_transactions': [],
        'contracts': [],
        'signed_contracts': [],
        'terminated_contracts': [],
        'timestamp': test_time,
        '_hash': 'block_send_test'
    }
    assert actual == expected
    def generate_from_priv(private_key):
        time_now = 1520135639.4713802
        public = EcdsaHashing.recover_public_key_str(private_key)
        transactions = [
            Transaction('', '', public, '', 1, 1, time_now),
            Transaction('', '', public, '', 10, 1, time_now),
            Transaction('', '', public, '', 100, 1, time_now),
            Transaction('', '', public, '', 1000, 1, time_now),
        ]

        for tranaction in transactions:
            tranaction.update_signature(private_key)
            tranaction.update_hash()

        pos_transactions = [PosTransaction('', '', public, 100, 1, time_now)]

        for pos_transaction in pos_transactions:
            pos_transaction.update_signature(private_key)
            pos_transaction.update_hash()

        block = Block('', '', public, '', 0, transactions, pos_transactions,
                      [], [], [], [], time_now)
        block.update_signature(private_key)
        block.update_hash()
        return block
def test_get_store_block():
    test_time = int(time.time())
    t1 = Transaction('transaction_test_1', '', 'matt', 'will', 45, 0,
                     test_time)
    t2 = Transaction('transaction_test_2', '', 'matt', 'denys', 7, 0,
                     test_time)
    t3 = Transaction('transaction_test_3', '', 'denys', 'steven', 33, 0,
                     test_time)
    t4 = Transaction('transaction_test_4', '', 'steven', 'naween', 5040, 0,
                     test_time)
    t5 = Transaction('transaction_test_5', '', 'will', 'naween', 22, 0,
                     test_time)
    t6 = Transaction('transaction_test_6', '', 'naween', 'matt', 588, 0,
                     test_time)
    b = Block('block_service_test_1', '', '', 'LAST_BLOCK', 0,
              [t1, t2, t3, t4, t5, t6], [], [], [], [], [], test_time)
    bs = BlockService()

    bs.store_block(b)

    new_b = bs.find_by_hash('block_service_test_1')
    b_send = b.get_sendable()
    new_send = new_b.get_sendable()
    assert b_send == new_send
Example #8
0
    def mine_block(miner_priv_key, last_block):
        balances = BlockService.get_all_balances()

        transactions = BaseObjectService.get_all_mempool_objects(Transaction)
        transactions_to_add = []
        for transaction in transactions:
            if len(transactions_to_add) == 100:
                break
            valid, balances = Miner.validate_transaction(balances, transaction)
            if valid:
                transactions_to_add.append(transaction)

        pos_transactions = BaseObjectService.get_all_mempool_objects(
            PosTransaction)
        pos_transactions_to_add = []
        for pos_transaction in pos_transactions:
            if len(pos_transactions_to_add) == 10:
                break
            valid, balances = Miner.validate_pos_transaction(
                balances, pos_transaction)
            if valid:
                pos_transactions_to_add.append(pos_transaction)

        contract_transactions = BaseObjectService.get_all_mempool_objects(
            ContractTransaction)
        contract_transactions_to_add = []
        for contract_transaction in contract_transactions:
            if len(contract_transactions_to_add) == 10:
                break
            valid, balances = Miner.validate_contract_transaction(
                balances, contract_transaction)
            if valid:
                contract_transactions_to_add.append(contract_transaction)

        contracts = BaseObjectService.get_all_mempool_objects(Contract)
        contracts_to_add = []
        for contract in contracts:
            if len(contracts_to_add) == 20:
                break
            valid, balances = Miner.validate_contract(balances, contract)
            if valid:
                contracts_to_add.append(contract)

        signed_contracts = BaseObjectService.get_all_mempool_objects(
            SignedContract)
        signed_contracts_to_add = []
        for signed_contract in signed_contracts:
            print('signed_contract:' + signed_contract._hash)
            if len(signed_contracts_to_add) == 20:
                break
            valid, balances = Miner.validate_signed_contract(
                balances, signed_contract)
            if valid:
                signed_contracts_to_add.append(signed_contract)

        terminated_contracts_to_add = []
        signed_contracts_to_check = SignedContractService.get_all_open_signed_contracts(
        )
        for sc_to_check in signed_contracts_to_check:
            print('signed_c to check: ' + sc_to_check._hash)
            end_time = sc_to_check.signed_timestamp + sc_to_check.duration
            now = int(time.time())
            # print('signed_time=' + str(sc_to_check.signed_timestamp) + ' duration=' + str(sc_to_check.duration) + ' end time='+ str(end_time) + '  now=' + str(now) + '   end<=now=' + str(end_time<=now))
            if end_time <= now:
                rs = RedisService()
                r = rs._connect()
                prices = r.zrangebyscore('price_stamps',
                                         end_time - 2000,
                                         end_time + 2000,
                                         withscores=True)
                if len(prices) != 0:
                    price = min(prices, key=lambda x: abs(x[1] - end_time))
                    print('terminated contract: ' + sc_to_check._hash)
                    tc = TerminatedContract(sc_to_check._hash, price[0],
                                            end_time)
                    terminated_contracts_to_add.append(tc)
                else:
                    print('no prices found')

        last_block_hash = last_block._hash
        miner_pub_key = EcdsaHashing.recover_public_key_str(miner_priv_key)
        height = last_block.height + 1
        block = Block('', '', miner_pub_key, last_block_hash, height,
                      transactions_to_add, pos_transactions_to_add,
                      contract_transactions_to_add, contracts_to_add,
                      signed_contracts_to_add, terminated_contracts_to_add,
                      time.time())
        block.update_signature(miner_priv_key)
        block.update_hash()
        return block
def regular_node_callback(data, peer_id=None):
    global kill_threads
    if kill_threads:
        return
    do_block_resend = False
    do_transaction_resend = True
    do_contract_resend = True
    sync_transaction = False
    sync_block = False
    sync_contract = False
    signed_contract_flag = False
    contract_transaction_flag = False
    pos_transaction_flag = False
    json_dic = json.loads(data)
    new_msg = message.Message.from_dict(json_dic)
    # sync block is the same as block, but they don't
    # need to be resend
    if new_msg.action == 'block_sync':
        new_msg.action = 'block'
        do_block_resend = False
        sync_block = True
    elif new_msg.action == 'transaction_sync' or new_msg.action == 'transaction_pos_sync' or new_msg.action == 'transaction_contract_sync':
        if new_msg.action == 'transaction_sync':
            new_msg.action = 'transaction'
        elif new_msg.action == 'transaction_pos_sync':
            new_msg.action = 'transaction_pos'
        elif new_msg.action == 'transaction_contract_sync':
            new_msg.action = 'transaction_contract'
        do_transaction_resend = False
        sync_transaction = True
    elif new_msg.action == 'contract_sync' or new_msg.action == 'contract_signed_sync':
        if new_msg.action == 'contract_sync':
            new_msg.action = 'contract'
        elif new_msg.action == 'contract_signed_sync':
            new_msg.action = 'contract_signed'
        do_contract_resend = False
        sync_contract = True
    # case to set flags for special types of transactions and contracts
    if new_msg.action == 'contract_signed':
        new_msg.action = 'contract'
        signed_contract_flag = True
    elif new_msg.action == 'transaction_contract':
        new_msg.action = 'transaction'
        contract_transaction_flag = True
    elif new_msg.action == 'transaction_pos':
        new_msg.action = 'transaction'
        pos_transaction_flag = True
    if new_msg.action == 'transaction':
        if contract_transaction_flag:
            print('\nContract Transaction')
            new_msg.data = ContractTransaction.from_dict(new_msg.data)
            object_to_check = ContractTransaction
            transaction_action = 'transaction_contract'
        elif pos_transaction_flag:
            print('\nPOS Transaction')
            new_msg.data = PosTransaction.from_dict(new_msg.data)
            object_to_check = PosTransaction
            transaction_action = 'transaction_pos'
        else:
            print('\nNormal Transaction')
            new_msg.data = Transaction.from_dict(new_msg.data)
            object_to_check = Transaction
            transaction_action = 'transaction'
        new_transaction = new_msg.data
        need_to_send = False
        transaction_lock.acquire()
        print('\nTransaction : {}'.format(new_transaction._hash))
        if not check_if_object_exist(new_transaction._hash, object_to_check):
            if a_node.doing_transaction_sync and not sync_transaction:
                a_node.transaction_queue.append(new_transaction)
                print('Added transaction to the queue')
            else:
                rs = redis_service.RedisService()
                rs.store_object(new_transaction)
                need_to_send = True
                print('All good')
        else:
            print('Duplicate transaction')
        transaction_lock.release()
        if need_to_send and do_transaction_resend:
            send_a_transaction(new_transaction, action=transaction_action)
    elif new_msg.action == 'contract':
        if signed_contract_flag:
            print('\nSigned Contract')
            new_msg.data = SignedContract.from_dict(new_msg.data)
            object_to_check = SignedContract
            method_to_call = SignedContractService.store_signed_contract
            contract_action = 'contract_signed'
        else:
            print('\nNormal Contract')
            new_msg.data = Contract.from_dict(new_msg.data)
            object_to_check = Contract
            method_to_call = ContractService.store_contract
            contract_action = 'contract'
        new_contract = new_msg.data
        need_to_send = False
        contract_lock.acquire()
        print('Contract : {}'.format(new_contract._hash))
        if not check_if_object_exist(new_contract._hash, object_to_check):
            if a_node.doing_contract_sync and not sync_contract:
                a_node.contract_queue.append([new_contract, method_to_call])
                print('Added contract to the queue')
            else:
                method_to_call(new_contract)
                need_to_send = True
                print('All good')
        else:
            print('Duplicate contract')
        contract_lock.release()
        if need_to_send and do_contract_resend:
            send_a_contract(new_contract, action=contract_action)
    elif new_msg.action == 'transaction_sync_end':
        print('\n\nFinished transaction sync')
        a_node.doing_transaction_sync = False
        a_node.add_transactions_from_queue()
    elif new_msg.action == 'block_sync_end':
        print('\n\nFinished block sync')
        a_node.doing_blockchain_sync = False
        # after we have added all sync blocks
        # we need to add normal blocks
        # that were send while we where doing sync
        a_node.add_blocks_from_queue()
    elif new_msg.action == 'contract_sync_end':
        print('\n\nFinished contract sync')
        a_node.doing_contract_sync = False
        a_node.add_contracts_from_queue()
    elif new_msg.action == 'init_sync_contract':
        print('Contract sync request')
        mem_contracts = BaseObjectService.get_all_mempool_objects(Contract)
        print('I have {} contracts'.format(len(mem_contracts)))
        mem_signed_contracts = BaseObjectService.get_all_mempool_objects(
            SignedContract)
        print('I have {} signed contracts'.format(len(mem_signed_contracts)))
        contract_lock.acquire()
        for a_contract in mem_contracts:
            send_a_contract(a_contract,
                            action='contract_sync',
                            contract_target_peer_id=peer_id)
        for a_signed_contract in mem_signed_contracts:
            send_a_contract(a_signed_contract,
                            action='contract_signed_sync',
                            contract_target_peer_id=peer_id)
        ending_msg = message.Message(action='contract_sync_end', data='')
        json_dic = ending_msg.to_json(is_object=False)
        json_str = json.dumps(json_dic, sort_keys=True, separators=(',', ':'))
        a_node.connection_manager.send_msg(msg=json_str,
                                           target_peer_id=peer_id)
        contract_lock.release()
    elif new_msg.action == 'init_sync_trans':
        print('Transaction sync request')
        mem_transactions = TransactionService.get_all_mempool_transactions()
        print('I have {} mem transactions'.format(len(mem_transactions)))
        mem_pos_transactions = BaseObjectService.get_all_mempool_objects(
            PosTransaction)
        print('I have {} mem pos transactions'.format(
            len(mem_pos_transactions)))
        mem_contract_transactions = BaseObjectService.get_all_mempool_objects(
            ContractTransaction)
        print('I have {} mem contract transactions'.format(
            len(mem_contract_transactions)))
        transaction_lock.acquire()
        for a_transaction in mem_transactions:
            send_a_transaction(a_transaction,
                               action='transaction_sync',
                               transaction_target_peer_id=peer_id)
        for a_pos_transaction in mem_pos_transactions:
            send_a_transaction(a_pos_transaction,
                               action='transaction_pos_sync',
                               transaction_target_peer_id=peer_id)
        for a_contract_transaction in mem_contract_transactions:
            send_a_transaction(a_contract_transaction,
                               action='transaction_contract_sync',
                               transaction_target_peer_id=peer_id)
        ending_msg = message.Message(action='transaction_sync_end', data='')
        json_dic = ending_msg.to_json(is_object=False)
        json_str = json.dumps(json_dic, sort_keys=True, separators=(',', ':'))
        a_node.connection_manager.send_msg(msg=json_str,
                                           target_peer_id=peer_id)
        transaction_lock.release()
    elif new_msg.action == 'init_sync':
        print('\nGot init sync, height is {}'.format(new_msg.data))
        peer_height = new_msg.data
        my_height = BlockService.get_max_height()
        # only do sync if we need to send blocks to a peer
        if peer_height < my_height:
            print('My height is higher, {}'.format(my_height))
            bs = dal_service_block_service.BlockService()
            list_of_blocks = bs.get_blocks_after_height(peer_height)
            block_lock.acquire()
            for a_block in list_of_blocks:
                send_a_block(a_block,
                             action='block_sync',
                             block_target_peer_id=peer_id)
            ending_msg = message.Message(action='block_sync_end', data='')
            json_dic = ending_msg.to_json(is_object=False)
            json_str = json.dumps(json_dic,
                                  sort_keys=True,
                                  separators=(',', ':'))
            a_node.connection_manager.send_msg(msg=json_str,
                                               target_peer_id=peer_id)
            block_lock.release()
        else:
            print('Same height')
            ending_msg = message.Message(action='block_sync_end', data='')
            json_dic = ending_msg.to_json(is_object=False)
            json_str = json.dumps(json_dic,
                                  sort_keys=True,
                                  separators=(',', ':'))
            a_node.connection_manager.send_msg(msg=json_str,
                                               target_peer_id=peer_id)
    elif new_msg.action == 'block':
        block_service = BlockService()
        new_block = Block.from_dict(new_msg.data)

        bs = dal_service_block_service.BlockService()

        need_to_send = False
        need_to_mine_new = False
        block_lock.acquire()
        print('\nBlock : {}'.format(new_block._hash))
        # if the node is doing blockchain sync
        # and this block is not sync block
        # we need to add it to the queue
        if a_node.doing_blockchain_sync and not sync_block:
            a_node.block_queue.append(new_block)
            result_list = []
        else:
            if Miner.validate_incoming_block(new_block):
                result_list = block_service.add_block_to_chain(new_block)
                if result_list:
                    need_to_mine_new = True
            else:
                result_list = []
        if result_list:
            need_to_send = True
            print('All good')
        else:
            if a_node.doing_blockchain_sync and not sync_block:
                print('Added block to a queue')
            else:
                print('Duplicate block')
        block_lock.release()
        if need_to_send and do_block_resend:
            send_a_block(new_block)

        need_to_mine_new = False
        if need_to_mine_new:
            for new_block_callback in new_block_callbacks:
                new_block_callback(new_block)
    def find_by_hash(self, block_hash):
        """
        Find a block using it's hash. Will return the block object, fully populated with all of the objects encased in it.

        Arguments:
        block_hash      -- hash of the block to retrieve

        Returns:
        block object    -- Block object containing all of the objects included in the block
        """
        r = self._connect()

        #rs = RedisService()

        # get key to retrieve list of block's fields
        name = self.key_suffix + block_hash

        if r.exists(name):
            # get all of the fields in the list
            hashes = r.lrange(name, 0, -1)

            # timestamp will always be first
            prev_block = hashes[0]
            # remove for iteration
            hashes.remove(prev_block)

            # timestamp will always be first
            height = hashes[0]
            # remove for iteration
            hashes.remove(height)

            # timestamp will always be first
            owner = hashes[0]
            # remove for iteration
            hashes.remove(owner)

            # timestamp will always be first
            signature = hashes[0]
            # remove for iteration
            hashes.remove(signature)

            # timestamp will always be first
            timestamp = hashes[0]
            # remove for iteration
            hashes.remove(timestamp)

            prefix = ''
            # list to hold all of the objects
            transactions = []
            pos_transactions = []
            contract_transactions = []
            contracts = []
            signed_contracts = []
            terminated_contracts = []

            # temporary list to copy from
            temp_list = []
            obj = None
            contract_section = False
            signed_contract_section = False
            terminated_contract_section = False
            for h in hashes:
                # if at a new type of object, change some variables
                if h == 'transactions':
                    prefix = Transaction._to_index()[-1]
                    obj = Transaction
                    continue
                elif h == 'pos_transactions':
                    prefix = PosTransaction._to_index()[-1]
                    obj = PosTransaction
                    transactions = temp_list.copy()
                    temp_list.clear()
                    continue
                elif h == 'contract_transactions':
                    prefix = ContractTransaction._to_index()[-1]
                    obj = ContractTransaction
                    pos_transactions = temp_list.copy()
                    temp_list.clear()
                    continue
                elif h == 'contracts':
                    contract_section = True
                elif h == 'signed_contracts':
                    contract_section = False
                    signed_contract_section = True
                elif h == 'terminated_contracts':
                    signed_contract_section = False
                    terminated_contract_section = True


                # get the object from redis and add to the temporary list
                if contract_section:
                    contract = ContractService.get_contract_by_hash(h)
                    if contract != None:
                        contracts.append(contract)
                elif signed_contract_section:
                    signed_contract = SignedContractService.get_signed_contract_by_hash(h)
                    if signed_contract != None:
                        signed_contracts.append(signed_contract)
                elif terminated_contract_section:
                    terminated_contract = self.rs.get_object_by_full_key('terminated_contract:' + h, TerminatedContract, r)
                    if terminated_contract != None:
                        terminated_contracts.append(terminated_contract)
                else:
                    t = self.rs.get_object_by_full_key(prefix + ":" + h, obj, r)
                    temp_list.append(t)

            contract_transactions = temp_list.copy()
            temp_list.clear()

            # create block object and return it
            block = Block(block_hash, signature, owner, prev_block, height, transactions, pos_transactions, contract_transactions, contracts, signed_contracts, terminated_contracts, timestamp)
            return block
        else:
            return None
def test_pos_author_two_blocks():
    expected = '23f48768a8e871db2ed721a1e0d250ce41a1fe49765e01e798db0816b781169115e01d3a702934276fa4536bb59527ba0cd7c2fd9eb9e3c13785750c4a9c31d0'
    r = redis.Redis()
    r.flushdb()
    genesis_block = {
        "height": 0,
        "prev_block": "",
        "_hash": "036850bec30839508bf16badc1efc5c0a31eb82f8b23c524c7ea8cd3d0c8b81f",
        "terminated_contracts": [],
        "signed_contracts": [],
        "contracts": [],
        "pos_transactions": [{
            "from_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "82b2704e380f4bc55c214d44f4cdd698ec3ed5471882d0ae67d80462f13434f5",
            "amount": "100.00000000",
            "signature": "2b6f4ad89868f8a820f682fb580a20b3383e9889b50736a66c8ed441ac4ebb29b7f32d6efe929b05d66de7ac0e20d0ea471f7a1e482f505f2f0df3221d720ba4"
        }],
        "contract_transactions": [],
        "timestamp": 1520135639,
        "owner": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
        "transactions": [{
            "to_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "f54029850ab8ffc3d3f1b210bee0008f1b42aa45e267925f42b80ed9eedb1c20",
            "amount": "1.00000000",
            "from_addr": "",
            "signature": "36a0131c4087dae1d0909baf5ea1b35c9955db7e775646df40d35ad6469469b21439e08263ab7a2fa03f3285fb13ce1b80b399bb6f254694e3f36b9ed5fa6a98"
        }, {
            "to_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "ac32ce4867f65d575d95109b59e713f180541cd5c76ca93dad7cea210ebfa26c",
            "amount": "10.00000000",
            "from_addr": "",
            "signature": "83abc47ca9ad48e91b63d6d4bba28786abfc7345f29f02dbf1c90b4e66f91413cf9a081314095d4bf30d508b9781d035a5816f13ea0c1f1d6b6dd59665697b15"
        }, {
            "to_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "e1e65c22699599507d2621b84a39b02ca525e5d3881c583d4d96cffdf3ceced7",
            "amount": "100.00000000",
            "from_addr": "",
            "signature": "998d03e220b28ad99b2b6d7a00cc1a06443ceea8a3a96acc896c6d8953b44d78f58a6cfbf699d5b4ed35f062cb05674d2f10718ecf44d07a300a781c21734220"
        }, {
            "to_addr": "c8fdd9558e4e36d3549c449986c587aa16be67439ed70b8bf1f7e47e8586572f4c821059e4077a94d3e31f1cfa8bccc5c2acf86e955d30ef93633bcabcdc9f34",
            "timestamp": 1520135639,
            "_hash": "b3cf3fba2d1b5e3ca6fee0b5d22a1b81f038ffd9e825119f1a7226e3e10a61ee",
            "amount": "1000.00000000",
            "from_addr": "",
            "signature": "556474088e1f4c75f24cb72db8b0be78134d10d0323c40569207baef1172c43b96596573a446389d2330d781109b76da8725d2ef29876cdd4a198fafc9cbf50f"
        }],
        "signature": "3a3a88935574c820fa70a2408f594585d03988df1980f6c0129b84ee129c322c683de1a7f8be6087d468abbbeb32f2a49eb0ac0c64a9b8de57d43a480ebf4dfc"
    }

    second_block = {
        '_hash': '1048eb4638a45b140a51e7a6d92e972010878d9f05be6fe5c0d20d17b4c26e7a',
        'height': 1,
        'contract_transactions': [],
        'transactions': [{
            'amount': '1.00000000',
            'to_addr': '23f48768a8e871db2ed721a1e0d250ce41a1fe49765e01e798db0816b781169115e01d3a702934276fa4536bb59527ba0cd7c2fd9eb9e3c13785750c4a9c31d0',
            'timestamp': 1520135639,
            '_hash': '188b1e41db5661c87777d7ea3d96cbe0b8858df2cd9c020abb4a424f91c22087',
            'from_addr': '',
            'signature': 'c3d5bdf941cf4a4a95483174e085da38cc4f7decb59cf07ce3ac80623de7e842f46b1d7f6880c358fe4b0ead324ba5af4176743bfd390daf34f79a6ed5e51de8'
        }, {
            'amount': '10.00000000',
            'to_addr': '23f48768a8e871db2ed721a1e0d250ce41a1fe49765e01e798db0816b781169115e01d3a702934276fa4536bb59527ba0cd7c2fd9eb9e3c13785750c4a9c31d0',
            'timestamp': 1520135639,
            '_hash': '004186e14438ea30c3d6ee69dfdc4b66d589e6d5d85c751bfae1220ecdbe8954',
            'from_addr': '',
            'signature': '8d02e40b4923aa1e9869ab48c8de423a510f966e6edb3def1013cf243fe9b7c6ab9c77fa485a02ff03fc769f9e1c36f9085210058d729ed4d71194d7e6c98335'
        }, {
            'amount': '100.00000000',
            'to_addr': '23f48768a8e871db2ed721a1e0d250ce41a1fe49765e01e798db0816b781169115e01d3a702934276fa4536bb59527ba0cd7c2fd9eb9e3c13785750c4a9c31d0',
            'timestamp': 1520135639,
            '_hash': '9463a74fa3e79a5a7f0dee4c8b0d06cdf5624dc529b2d1915cdffabfcdece8ff',
            'from_addr': '',
            'signature': '26962120d2621f61ce4281169d97a06fc508d0246e9779dc3d50a04382f469389166b040d54fab4f00b45fa4ef9ff69296709b1165afb1e695ff893124325e47'
        }, {
            'amount': '1000.00000000',
            'to_addr': '23f48768a8e871db2ed721a1e0d250ce41a1fe49765e01e798db0816b781169115e01d3a702934276fa4536bb59527ba0cd7c2fd9eb9e3c13785750c4a9c31d0',
            'timestamp': 1520135639,
            '_hash': '79ba95186cf2068aa7868057661e315856e44d43a7b3e1fdebfdd9cf7e9679d1',
            'from_addr': '',
            'signature': '5b8dfb857bbee98edc869948bcd90b361d2a9ac48704981cd4a4697ae090b22bf3389b2a0d17ed198f7c9aaa98baa68db5d869279a5065c6ebb44dcb628d06f7'
        }],
        'timestamp': 1520135642,
        'terminated_contracts': [],
        'signed_contracts': [],
        'contracts': [],
        'prev_block': '036850bec30839508bf16badc1efc5c0a31eb82f8b23c524c7ea8cd3d0c8b81f',
        'signature': '829ac7859ca675ea410a781cf30b39fd7864daeda054c50893001da164d04cfacab103dc57cb9d39e545b8533dbd8d54954c3399c01bc356c06801e48242d531',
        'owner': '23f48768a8e871db2ed721a1e0d250ce41a1fe49765e01e798db0816b781169115e01d3a702934276fa4536bb59527ba0cd7c2fd9eb9e3c13785750c4a9c31d0',
        'pos_transactions': [{
            '_hash': '1d1d4247b7611a28e66b114a14445e894dfb7086accb8d02f6f1ac06ff15e049',
            'amount': '100.00000000',
            'from_addr': '23f48768a8e871db2ed721a1e0d250ce41a1fe49765e01e798db0816b781169115e01d3a702934276fa4536bb59527ba0cd7c2fd9eb9e3c13785750c4a9c31d0',
            'signature': 'b7e348c8ebe6e483279a22d1426d31122f14a4ea46b27b9fa85d2cd91b533abc463cafd85ddf524f3677daabf888a146f91721cac26a17568a768a3c18956a15',
            'timestamp': 1520135639
        }]
    }
    dal_block_service = DalBlockService()

    block = Block.from_dict(genesis_block)
    dal_block_service.store_block(block)

    block = Block.from_dict(second_block)
    dal_block_service.store_block(block)

    actual = POSService.get_next_block_author(block)
    assert actual == expected