Esempio n. 1
0
    def test_prepare_address_list(self):
        with set_qrl_dir('no_data'):
            with State() as state:
                block = Block.create(block_number=10,
                                     prev_headerhash=b'',
                                     prev_timestamp=10,
                                     transactions=[],
                                     miner_address=get_some_address(1))
                # Test Case: without any transactions of block
                self.assertEqual(state.prepare_address_list(block),
                                 {config.dev.coinbase_address, get_some_address(1)})

                alice_xmss = get_alice_xmss()
                block = Block.create(block_number=10,
                                     prev_headerhash=b'',
                                     prev_timestamp=10,
                                     transactions=[TransferTransaction.create(addrs_to=[get_some_address(2),
                                                                                        get_some_address(3)],
                                                                              amounts=[100, 100],
                                                                              fee=0,
                                                                              xmss_pk=alice_xmss.pk)],
                                     miner_address=get_some_address(1))

                # Test Case, with one Transaction
                self.assertEqual(state.prepare_address_list(block),
                                 {config.dev.coinbase_address,
                                  get_some_address(1),
                                  get_some_address(2),
                                  get_some_address(3),
                                  alice_xmss.address})
Esempio n. 2
0
 def test_delete(self):
     block = Block()
     self.state.put_block(block, None)
     block1 = self.state.get_block(block.headerhash)
     self.assertEqual(block.serialize(), block1.serialize())
     self.state._delete(block.headerhash, None)
     self.assertIsNone(self.state.get_block(block.headerhash))
Esempio n. 3
0
    def test_getBlock(self):
        with set_qrl_dir('no_data'):
            db_state = State()

            p2p_factory = Mock(spec=P2PFactory)
            p2p_factory.pow = Mock(spec=POW)

            chain_manager = ChainManager(db_state)

            qrlnode = QRLNode(mining_address=b'')
            qrlnode.set_chain_manager(chain_manager)
            qrlnode._p2pfactory = p2p_factory
            qrlnode._pow = p2p_factory.pow
            qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1']

            service = PublicAPIService(qrlnode)

            alice_xmss = get_alice_xmss()
            b = Block.create(dev_config=config.dev,
                             block_number=1,
                             prev_headerhash=sha256(b'reveal'),
                             prev_timestamp=10,
                             transactions=[],
                             miner_address=alice_xmss.address,
                             seed_height=0,
                             seed_hash=None)
            Block.put_block(db_state, b, None)
            db_state.get_block = MagicMock(return_value=b)

            context = Mock(spec=ServicerContext)
            request = qrl_pb2.GetBlockReq(header_hash=b.headerhash)
            response = service.GetBlock(request=request, context=context)
            context.set_code.assert_not_called()
            self.assertEqual(1, response.block.header.block_number)
Esempio n. 4
0
    def start_mining(self,
                     mining_block: Block,
                     current_target: bytes,
                     dev_config: DevConfig):
        try:
            logger.debug('start_mining - TRY LOCK')
            with self.lock:
                logger.debug('start_mining - LOCKED')
                self.cancel()

                mining_blob = mining_block.mining_blob(dev_config)
                nonce_offset = mining_block.mining_nonce_offset(dev_config)

                seed_block = self.get_seed_block(mining_block.block_number)

                self._dev_config = dev_config
                self._mining_block = mining_block
                work_seq_id = self.start(mainHeight=mining_block.block_number,
                                         seedHeight=seed_block.block_number,
                                         seedHash=seed_block.headerhash,
                                         input=mining_blob,
                                         nonceOffset=nonce_offset,
                                         target=current_target,
                                         thread_count=self._mining_thread_count)

                logger.debug("MINING START [{}]".format(work_seq_id))

        except Exception as e:
            logger.warning("Exception in start_mining")
            logger.exception(e)

        logger.debug('start_mining - UNLOCKED')
Esempio n. 5
0
    def pre_block_logic(self, block: Block):
        logger.debug('Checking miner lock')
        with self._miner_lock:
            if not block.validate(self.chain_manager.state,
                                  self.future_blocks):
                logger.warning('Block Validation failed for #%s %s',
                               block.block_number, bin2hstr(block.headerhash))
                return

            if block.is_future_block():
                delay = abs(block.timestamp - ntp.getTime()) + 1
                reactor.callLater(delay, self.process_future_blocks)
                self.add_future_block(block)
                return

            logger.debug('Inside add_block')
            result = self.chain_manager.add_block(block)

            logger.debug('trigger_miner %s', self.chain_manager.trigger_miner)
            if self.chain_manager.trigger_miner:
                self.mine_next(self.chain_manager.last_block)

            if not result:
                logger.debug('Block Rejected %s %s', block.block_number,
                             bin2hstr(block.headerhash))
                return

            reactor.callLater(0, self.broadcast_block, block)
Esempio n. 6
0
    def pre_block_logic(self, block: Block):
        logger.debug('LOCK - TRY - pre_block_logic')
        with self.miner.lock:
            logger.debug('LOCK - LOCKED - pre_block_logic')

            if not block.validate(self.chain_manager, self.future_blocks):
                logger.warning('Block Validation failed for #%s %s', block.block_number, bin2hstr(block.headerhash))
                return False

            dev_config = self.chain_manager.get_config_by_block_number(block.block_number)
            if block.is_future_block(dev_config):
                delay = abs(block.timestamp - ntp.getTime()) + 1
                reactor.callLater(delay, self.process_future_blocks)
                self.add_future_block(block)
                return True

            logger.debug('Inside add_block')
            result = self.chain_manager.add_block(block)

            logger.debug('trigger_miner %s', self.chain_manager.trigger_miner)
            if self.chain_manager.trigger_miner:
                logger.debug('try last block')
                last_block = self.chain_manager.last_block
                logger.debug('got last block')
                self._mine_next(last_block)

            if not result:
                logger.debug('Block Rejected %s %s', block.block_number, bin2hstr(block.headerhash))
                return False

            reactor.callLater(0, self.broadcast_block, block)
        logger.debug('LOCK - RELEASE - pre_block_logic')

        return result
Esempio n. 7
0
 def test_get_block_by_number(self,
                              m_TransferTransaction_validate,
                              m_TransferTransaction_validate_extended,
                              m_TransferTransaction_apply_state_changes,
                              m_CoinBase_apply_state_changes):
     bm = qrl_pb2.BlockNumberMapping()
     Block.put_block_number_mapping(self.state, 0, bm, None)
     self.assertIsNone(Block.get_block_by_number(self.state, 4))
Esempio n. 8
0
 def test_delete(self):
     with set_qrl_dir('no_data'):
         with State() as state:
             block = Block()
             state.put_block(block, None)
             block1 = state.get_block(block.headerhash)
             self.assertEqual(block.serialize(), block1.serialize())
             state._delete(block.headerhash, None)
             self.assertIsNone(state.get_block(block.headerhash))
Esempio n. 9
0
    def create_block(self,
                     last_block,
                     mining_nonce,
                     tx_pool: TransactionPool,
                     miner_address) -> Optional[Block]:
        # TODO: Persistence will move to rocksdb
        # FIXME: Difference between this and create block?????????????

        dummy_block = Block.create(block_number=last_block.block_number + 1,
                                   prevblock_headerhash=last_block.headerhash,
                                   transactions=[],
                                   miner_address=miner_address)
        dummy_block.set_nonces(mining_nonce, 0)

        t_pool2 = tx_pool.transactions

        addresses_set = set()
        for tx_set in t_pool2:
            tx = tx_set[1]
            tx.set_effected_address(addresses_set)

        addresses_state = dict()
        for address in addresses_set:
            addresses_state[address] = self.state.get_address(address)

        block_size = dummy_block.size
        block_size_limit = self.state.get_block_size_limit(last_block)

        transactions = []
        for tx_set in t_pool2:
            tx = tx_set[1]
            # Skip Transactions for later, which doesn't fit into block
            if block_size + tx.size + config.dev.tx_extra_overhead > block_size_limit:
                continue

            addr_from_pk_state = addresses_state[tx.addr_from]
            addr_from_pk = Transaction.get_slave(tx)
            if addr_from_pk:
                addr_from_pk_state = addresses_state[addr_from_pk]

            if not tx.validate_extended(addresses_state[tx.addr_from], addr_from_pk_state):
                logger.warning('Txn validation failed for tx in tx_pool')
                tx_pool.remove_tx_from_pool(tx)
                continue

            tx.apply_on_state(addresses_state)

            tx._data.nonce = addr_from_pk_state.nonce
            block_size += tx.size + config.dev.tx_extra_overhead
            transactions.append(tx)

        block = Block.create(block_number=last_block.block_number + 1,
                             prevblock_headerhash=last_block.headerhash,
                             transactions=transactions,
                             miner_address=miner_address)

        return block
Esempio n. 10
0
    def create_block(self, last_block, mining_nonce, tx_pool: TransactionPool,
                     miner_address) -> Optional[Block]:
        dummy_block = Block.create(block_number=last_block.block_number + 1,
                                   prev_headerhash=last_block.headerhash,
                                   prev_timestamp=last_block.timestamp,
                                   transactions=[],
                                   miner_address=miner_address)
        dummy_block.set_nonces(mining_nonce, 0)

        t_pool2 = tx_pool.transactions

        addresses_set = set()
        for tx_set in t_pool2:
            tx = tx_set[1].transaction
            tx.set_affected_address(addresses_set)

        addresses_state = dict()
        for address in addresses_set:
            addresses_state[address] = self._chain_manager.get_address_state(
                address)

        block_size = dummy_block.size
        block_size_limit = self._chain_manager.get_block_size_limit(last_block)

        transactions = []
        for tx_set in t_pool2:
            tx = tx_set[1].transaction
            # Skip Transactions for later, which doesn't fit into block
            if block_size + tx.size + config.dev.tx_extra_overhead > block_size_limit:
                continue

            addr_from_pk_state = addresses_state[tx.addr_from]
            addr_from_pk = Transaction.get_slave(tx)
            if addr_from_pk:
                addr_from_pk_state = addresses_state[addr_from_pk]

            if not tx.validate_extended(addresses_state[tx.addr_from],
                                        addr_from_pk_state):
                logger.warning('Txn validation failed for tx in tx_pool')
                tx_pool.remove_tx_from_pool(tx)
                continue

            tx.apply_state_changes(addresses_state)

            tx._data.nonce = addr_from_pk_state.nonce
            block_size += tx.size + config.dev.tx_extra_overhead
            transactions.append(tx)

        block = Block.create(block_number=last_block.block_number + 1,
                             prev_headerhash=last_block.headerhash,
                             prev_timestamp=last_block.timestamp,
                             transactions=transactions,
                             miner_address=miner_address)

        return block
Esempio n. 11
0
    def test_get_block_size_limit(self):
        alice_xmss = get_alice_xmss()
        blocks = gen_blocks(20, self.state, alice_xmss.address)
        self.assertEqual(
            Block.get_block_size_limit(self.state, blocks[-1], config.dev),
            1048576)

        # get_block_size_limit() should return None if it couldn't get any blocks from db
        with patch('qrl.core.Block.Block.get_block', return_value=None):
            self.assertIsNone(
                Block.get_block_size_limit(self.state, blocks[-1], config.dev))
Esempio n. 12
0
 def test_get_block_number_mapping(self,
                                   m_TransferTransaction_validate,
                                   m_TransferTransaction_validate_extended,
                                   m_TransferTransaction_apply_state_changes,
                                   m_CoinBase_apply_state_changes):
     self.assertIsNone(Block.get_block_number_mapping(self.state, 0))
     bm = qrl_pb2.BlockNumberMapping()
     Block.put_block_number_mapping(self.state, 0, bm, None)
     read_bm = Block.get_block_number_mapping(self.state, 0)
     self.assertEqual(bm.SerializeToString(),
                      read_bm.SerializeToString())
Esempio n. 13
0
 def test_write_batch(self):
     batch = self.state.batch
     block = Block.create(dev_config=config.dev,
                          block_number=10,
                          prev_headerhash=b'aa',
                          prev_timestamp=10,
                          transactions=[],
                          miner_address=b'aa',
                          seed_height=0,
                          seed_hash=None)
     Block.put_block(self.state, block, batch)
     self.assertIsNone(Block.get_block(self.state, block.headerhash))
     self.state.write_batch(batch)
     block2 = Block.get_block(self.state, block.headerhash)
     self.assertEqual(block.headerhash, block2.headerhash)
Esempio n. 14
0
    def test_GetBlockMiningCompatible(self):
        p2p_factory = Mock(spec=P2PFactory)
        p2p_factory.sync_state = SyncState()
        p2p_factory.num_connections = 23
        p2p_factory.pow = Mock()

        chain_manager = Mock(spec=ChainManager)
        chain_manager.height = 0
        chain_manager.get_last_block = MagicMock(return_value=Block())

        qrlnode = QRLNode(mining_address=b'')
        qrlnode.set_chain_manager(chain_manager)
        qrlnode._p2pfactory = p2p_factory
        qrlnode._pow = p2p_factory.pow

        block_header = BlockHeader.create(blocknumber=10,
                                          prev_headerhash=sha256(b'prevblock'),
                                          prev_timestamp=1234567890,
                                          hashedtransactions=sha256(b'tx1'),
                                          fee_reward=1)

        qrlnode.get_blockheader_and_metadata = MagicMock(
            return_value=[block_header, BlockMetadata()])

        service = MiningAPIService(qrlnode)
        req = qrlmining_pb2.GetBlockMiningCompatibleReq(height=10)

        answer = service.GetBlockMiningCompatible(request=req, context=None)

        self.assertEqual(10, answer.blockheader.block_number)
        self.assertEqual(1, answer.blockheader.reward_fee)
Esempio n. 15
0
    def test_tx_validation_fails(self,
                                 m_TransferTransaction_validate,
                                 m_TransferTransaction_validate_extended,
                                 m_TransferTransaction_apply_state_changes,
                                 m_CoinBase_apply_state_changes):
        get_optimized_address_state = MockFunction()
        get_optimized_address_state.put(self.coinbase_addrstate_attrs.address, self.coinbase_addrstate_attrs)
        get_optimized_address_state.put(self.bob_addrstate_attrs.address, self.bob_addrstate_attrs)
        get_optimized_address_state.put(self.alice_addrstate_attrs.address, self.alice_addrstate_attrs)
        get_optimized_address_state.put(self.slave_addrstate_attrs.address, self.slave_addrstate_attrs)

        block = Block.create(**self.block_attrs)

        m_TransferTransaction_validate.return_value = False
        result = self.chain_manager._apply_state_changes(block, None)
        self.assertFalse(result)
        m_TransferTransaction_validate.return_value = True

        m_TransferTransaction_validate_extended.return_value = False
        result = self.chain_manager._apply_state_changes(block, None)
        self.assertFalse(result)
        m_TransferTransaction_validate_extended.return_value = True

        with patch('qrl.core.txs.CoinBase.CoinBase._validate_extended') as m_validate_extended:
            m_validate_extended.return_value = False
            result = self.chain_manager._apply_state_changes(block, None)
            self.assertFalse(result)
Esempio n. 16
0
    def test_bad_nonce_or_ots_reused(self,
                                     m_TransferTransaction_validate,
                                     m_TransferTransaction_validate_extended,
                                     m_TransferTransaction_apply_state_changes,
                                     m_CoinBase_apply_state_changes):
        # If a TX was signed by a Slave XMSS, apply_state_changes() should check against the Slave's AddressState.nonce.
        # In this case, tx.nonce = 3 but slave addrstate.nonce = 0
        self.slave_addrstate_attrs.pbdata.nonce = 0
        get_optimized_address_state = MockFunction()
        get_optimized_address_state.put(self.coinbase_addrstate_attrs.address, self.coinbase_addrstate_attrs)
        get_optimized_address_state.put(self.bob_addrstate_attrs.address, self.bob_addrstate_attrs)
        get_optimized_address_state.put(self.alice_addrstate_attrs.address, self.alice_addrstate_attrs)
        get_optimized_address_state.put(self.slave_addrstate_attrs.address, self.slave_addrstate_attrs)

        block = Block.create(**self.block_attrs)
        result = self.chain_manager._apply_state_changes(block, None)
        self.assertFalse(result)
        self.slave_addrstate_attrs.pbdata.nonce = 5

        # Now we pretend that Alice's OTS key has been reused.
        result = self.chain_manager._apply_state_changes(block, None)
        self.assertFalse(result)

        # Now we pretend that Slave's OTS key has been reused.
        result = self.chain_manager._apply_state_changes(block, None)
        self.assertFalse(result)
Esempio n. 17
0
    def test_mining_blob(self):
        alice_xmss = get_alice_xmss()
        block = Block.create(block_number=5,
                             prevblock_headerhash=bytes(sha2_256(b'test')),
                             transactions=[],
                             miner_address=alice_xmss.address)

        block.set_nonces(mining_nonce=5, extra_nonce=4)

        mining_blob = block.mining_blob
        self.assertEqual(len(mining_blob), config.dev.mining_blob_size)
        mining_nonce_bytes = mining_blob[config.dev.mining_nonce_offset:config.
                                         dev.mining_nonce_offset + 4]
        extra_nonce_bytes = mining_blob[config.dev.extra_nonce_offset:config.
                                        dev.extra_nonce_offset + 8]

        mining_nonce = int.from_bytes(mining_nonce_bytes,
                                      byteorder='big',
                                      signed=False)
        extra_nonce = int.from_bytes(extra_nonce_bytes,
                                     byteorder='big',
                                     signed=False)

        self.assertEqual(mining_nonce, 5)
        self.assertEqual(extra_nonce, 4)
Esempio n. 18
0
    def test_last_block(self):
        with set_wallet_dir("test_wallet"):
            with State() as state:
                self.assertIsNotNone(state)

                chain = Chain(state)
                alice_xmss = get_alice_xmss()
                staking_address = bytes(alice_xmss.get_address().encode())

                address_state_dict = dict()
                address_state_dict[staking_address] = AddressState.create(address=staking_address,
                                                                          nonce=0,
                                                                          balance=100,
                                                                          pubhashes=[])

                tmp_block1 = Block.create(staking_address=staking_address,
                                          block_number=0,
                                          reveal_hash=bytes(),
                                          prevblock_headerhash=bytes(),
                                          transactions=[],
                                          duplicate_transactions=OrderedDict(),
                                          vote=VoteMetadata(),
                                          signing_xmss=alice_xmss,
                                          nonce=address_state_dict[staking_address].nonce + 1)

                res = chain.add_block(tmp_block1, address_state_dict, None)
                address_state_dict[staking_address].increase_nonce()
                address_state_dict[staking_address].balance += tmp_block1.block_reward
                self.assertTrue(res)
                self.assertEqual(0, chain.height)           # FIXME: wrong name, it is not height but max_index

                last_block = chain.get_last_block()
                self.assertEqual(tmp_block1, last_block)
Esempio n. 19
0
    def test_simple_add_block(self, time_mock):
        # Simply test that adding a block on top of the genesis block works.
        self.chain_manager._difficulty_tracker.get.return_value = ask_difficulty_tracker(
            '2')
        self.chain_manager.load(self.genesis_block)

        time_mock.return_value = 1615270948  # Very high to get an easy difficulty

        block_1 = Block.create(block_number=1,
                               prev_headerhash=self.genesis_block.headerhash,
                               prev_timestamp=self.genesis_block.timestamp,
                               transactions=[],
                               miner_address=alice.address)
        block_1.set_nonces(201, 0)

        # Uncomment only to determine the correct mining_nonce of above blocks
        # from qrl.core.PoWValidator import PoWValidator
        # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False):
        #     block_1.set_nonces(block_1.mining_nonce + 1)
        #     print(block_1.mining_nonce)
        self.assertTrue(block_1.validate(self.chain_manager, {}))
        result = self.chain_manager.add_block(block_1)

        self.assertTrue(result)
        self.assertEqual(self.chain_manager.last_block, block_1)
Esempio n. 20
0
    def test_rollback_tx_metadata(self):
        alice_xmss = get_alice_xmss()

        tx1 = TransferTransaction.create(
            addrs_to=[get_some_address(1),
                      get_some_address(2)],
            amounts=[1, 2],
            message_data=None,
            fee=0,
            xmss_pk=alice_xmss.pk)

        block = Block.create(dev_config=config.dev,
                             block_number=5,
                             prev_headerhash=b'',
                             prev_timestamp=10,
                             transactions=[tx1],
                             miner_address=b'',
                             seed_height=0,
                             seed_hash=None)

        TransactionMetadata.update_tx_metadata(self.state,
                                               block=block,
                                               batch=None)

        tx_metadata = TransactionMetadata.get_tx_metadata(
            self.state, tx1.txhash)

        self.assertEqual(tx_metadata[0].to_json(), tx1.to_json())
        TransactionMetadata.rollback_tx_metadata(self.state, block, None)
        self.assertIsNone(
            TransactionMetadata.get_tx_metadata(self.state, tx1.txhash))
Esempio n. 21
0
    def test_bad_nonce_or_ots_reused(self, m_TransferTransaction_validate,
                                     m_TransferTransaction_validate_extended,
                                     m_TransferTransaction_apply_state_changes,
                                     m_CoinBase_apply_state_changes):
        # If a TX was signed by a Slave XMSS, apply_state_changes() should check against the Slave's AddressState.nonce.
        # In this case, tx.nonce = 3 but slave addrstate.nonce = 0
        self.slave_addrstate_attrs['nonce'] = 0
        address_states = self.generate_address_states(
            self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs)

        block = Block.create(**self.block_attrs)
        result = block.apply_state_changes(address_states)
        self.assertFalse(result)
        self.slave_addrstate_attrs['nonce'] = 5

        # Now we pretend that Alice's OTS key has been reused.
        self.alice_addrstate_attrs['ots_key_reuse.return_value'] = True
        address_states = self.generate_address_states(
            self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs)
        result = block.apply_state_changes(address_states)
        self.assertFalse(result)
        self.alice_addrstate_attrs['ots_key_reuse.return_value'] = False

        # Now we pretend that Slave's OTS key has been reused.
        self.slave_addrstate_attrs['ots_key_reuse.return_value'] = True
        address_states = self.generate_address_states(
            self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs)
        result = block.apply_state_changes(address_states)
        self.assertFalse(result)
Esempio n. 22
0
    def create_block(self, prev_hash, mining_address=None):
        if not mining_address:
            mining_address = self.alice_xmss.address
        transactions = []
        block_prev = self.qrlnode.get_block_from_hash(prev_hash)
        block_idx = block_prev.block_number + 1

        if block_idx == 1:
            slave_tx = SlaveTransaction.create(slave_pks=[self.bob_xmss.pk],
                                               access_types=[0],
                                               fee=0,
                                               xmss_pk=self.alice_xmss.pk)
            slave_tx.sign(self.alice_xmss)
            slave_tx._data.nonce = 1
            transactions = [slave_tx]

        time_offset = 60
        if block_idx % 2 == 0:
            time_offset += 2

        self.time_mock.return_value = self.time_mock.return_value + time_offset
        self.ntp_mock.return_value = self.ntp_mock.return_value + time_offset

        block_new = Block.create(block_number=block_idx,
                                 prev_headerhash=block_prev.headerhash,
                                 prev_timestamp=block_prev.timestamp,
                                 transactions=transactions,
                                 miner_address=mining_address)

        while not self.qrlnode._chain_manager.validate_mining_nonce(blockheader=block_new.blockheader):
            block_new.set_nonces(block_new.mining_nonce + 1, 0)

        return block_new
Esempio n. 23
0
def main():
    if len(sys.argv) > 2:
        print("Unexpected arguments")
        sys.exit(0)
    elif len(sys.argv) == 1:
        print("Missing Filename")
        sys.exit(0)

    filename = sys.argv[1]

    if sys.version_info.major > 2:
        seed = bytes(hstr2bin(input('Enter extended hexseed: ')))
    else:
        seed = bytes(hstr2bin(raw_input('Enter extended hexseed: ')))  # noqa

    dist_xmss = XMSS.from_extended_seed(seed)

    transactions = get_migration_transactions(signing_xmss=dist_xmss, filename=filename)

    block = Block.create(dev_config=config.dev,
                         block_number=0,
                         prev_headerhash=config.user.genesis_prev_headerhash,
                         prev_timestamp=config.user.genesis_timestamp,
                         transactions=transactions,
                         miner_address=dist_xmss.address,
                         seed_height=None,
                         seed_hash=None)

    block.set_nonces(config.dev, 0, 0)

    block._data.genesis_balance.extend([qrl_pb2.GenesisBalance(address=config.dev.coinbase_address,
                                                               balance=105000000000000000)])

    with open('genesis.yml', 'w') as f:
        yaml.dump(json.loads(block.to_json()), f)
Esempio n. 24
0
    def setUp(self):
        p2p_factory = Mock(spec=P2PFactory)
        p2p_factory.sync_state = SyncState()
        p2p_factory.num_connections = 23
        p2p_factory.pow = Mock()
        b = Block()
        self.chain_manager = Mock(spec=ChainManager)
        self.chain_manager.height = 0
        self.chain_manager.get_last_block = MagicMock(return_value=b)
        self.chain_manager.get_block_header_hash_by_number = MagicMock(
            return_value=b.headerhash)

        self.qrlnode = QRLNode(mining_address=b'')
        self.qrlnode.set_chain_manager(self.chain_manager)
        self.qrlnode._p2pfactory = p2p_factory
        self.qrlnode._pow = p2p_factory.pow

        self.block_header_params = {
            "dev_config": config.dev,
            "blocknumber": 10,
            "prev_headerhash": sha256(b'prevblock'),
            "prev_timestamp": 1234567890,
            "hashedtransactions": sha256(b'tx1'),
            "fee_reward": 1,
            "seed_height": 0,
            "seed_hash": None,
        }

        self.service = MiningAPIService(self.qrlnode)
Esempio n. 25
0
    def test_getBlockByNumber(self):
        db_state = Mock(spec=State)
        db_state.get_tx_metadata = MagicMock(return_value=None)
        db_state.get_block = MagicMock(return_value=None)

        p2p_factory = Mock(spec=P2PFactory)
        p2p_factory.pow = Mock(spec=POW)

        chain_manager = ChainManager(db_state)

        qrlnode = QRLNode(mining_address=b'')
        qrlnode.set_chain_manager(chain_manager)
        qrlnode._p2pfactory = p2p_factory
        qrlnode._pow = p2p_factory.pow
        qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1']

        service = PublicAPIService(qrlnode)

        alice_xmss = get_alice_xmss()
        b = Block.create(block_number=1,
                         prev_headerhash=sha256(b'reveal'),
                         prev_timestamp=10,
                         transactions=[],
                         miner_address=alice_xmss.address)
        db_state.get_block_by_number = MagicMock(return_value=b)

        context = Mock(spec=ServicerContext)
        request = qrl_pb2.GetBlockByNumberReq(block_number=b.block_number)
        response = service.GetBlockByNumber(request=request, context=context)
        context.set_code.assert_not_called()
        self.assertEqual(1, response.block.header.block_number)
Esempio n. 26
0
    def create_block(self, prev_hash):
        transactions = []
        block_prev = self.qrlnode.get_block_from_hash(prev_hash)
        block_idx = block_prev.block_number + 1

        if block_idx == 1:
            slave_tx = SlaveTransaction.create(slave_pks=[self.bob_xmss.pk],
                                               access_types=[0],
                                               fee=0,
                                               xmss_pk=self.alice_xmss.pk)
            slave_tx.sign(self.alice_xmss)
            slave_tx._data.nonce = 1
            transactions = [slave_tx]

        self.time_mock.return_value = self.time_mock.return_value + 60
        self.ntp_mock.return_value = self.ntp_mock.return_value + 60

        block_new = Block.create(block_number=block_idx,
                                 prevblock_headerhash=block_prev.headerhash,
                                 transactions=transactions,
                                 miner_address=self.alice_xmss.address)

        while not PoWValidator().validate_mining_nonce(state=self.qrlnode._chain_manager.state,
                                                       blockheader=block_new.blockheader,
                                                       enable_logging=False):
            block_new.set_mining_nonce(block_new.mining_nonce + 1)

        return block_new
Esempio n. 27
0
    def test_getKnownPeers(self):
        p2p_factory = Mock(spec=P2PFactory)
        p2p_factory.sync_state = SyncState()
        p2p_factory.num_connections = 23
        p2p_factory.pow = Mock()

        chain_manager = Mock(spec=ChainManager)
        chain_manager.height = 0
        chain_manager.last_block = Block()

        qrlnode = QRLNode(mining_address=b'')
        qrlnode.set_chain_manager(chain_manager)
        qrlnode._p2pfactory = p2p_factory
        qrlnode._pow = p2p_factory.pow
        qrlnode.peer_manager = Mock()
        qrlnode.peer_manager.known_peer_addresses = [
            '127.0.0.1', '192.168.1.1'
        ]

        service = PublicAPIService(qrlnode)
        response = service.GetKnownPeers(request=qrl_pb2.GetKnownPeersReq,
                                         context=None)

        self.assertEqual(2, len(response.known_peers))
        self.assertEqual('127.0.0.1', response.known_peers[0].ip)
        self.assertEqual('192.168.1.1', response.known_peers[1].ip)

        logger.info(response)
Esempio n. 28
0
    def __init__(self, state):
        self.state = state
        self.tx_pool = TransactionPool()  # TODO: Move to some pool manager
        self.last_block = Block.from_json(GenesisBlock().to_json())
        self.current_difficulty = StringToUInt256(str(config.dev.genesis_difficulty))

        self.trigger_miner = False
Esempio n. 29
0
    def handle_block(self, source,
                     message: qrllegacy_pb2.LegacyMessage):  # block received
        """
        Block
        This function processes any new block received.
        :return:
        """
        P2PBaseObserver._validate_message(message,
                                          qrllegacy_pb2.LegacyMessage.BK)
        try:
            block = Block(message.block)
        except Exception as e:
            logger.error(
                'block rejected - unable to decode serialised data %s',
                source.addr_remote)
            logger.exception(e)
            return

        logger.info('>>>Received block from %s %s %s', source.addr_remote,
                    block.block_number, bin2hstr(block.headerhash))

        if not source.factory.master_mr.isRequested(block.headerhash, source,
                                                    block):
            return

        source.factory.pow.pre_block_logic(
            block)  # FIXME: Ignores return value
        source.factory.master_mr.register(qrllegacy_pb2.LegacyMessage.BK,
                                          block.headerhash, message.block)
Esempio n. 30
0
def qrlnode_with_mock_blockchain(num_blocks):
    start_time = time.time()
    with mock.patch('qrl.core.misc.ntp.getTime') as ntp_mock, \
            set_data_dir('no_data'), \
            State() as state, \
            mock.patch('time.time') as time_mock:  # noqa
        time_mock.return_value = start_time
        ntp_mock.return_value = start_time

        state.get_measurement = MagicMock(return_value=10000000)

        required_height = ceil(log(num_blocks, 2))
        required_height = int(required_height + required_height % 2)

        alice_xmss = get_alice_xmss(xmss_height=required_height)
        bob_xmss = get_bob_xmss()

        genesis_block = GenesisBlock()
        chain_manager = ChainManager(state)
        chain_manager.load(genesis_block)

        chain_manager._difficulty_tracker = Mock()
        dt = DifficultyTracker()
        tmp_difficulty = StringToUInt256('2')
        tmp_target = dt.get_target(tmp_difficulty)

        chain_manager._difficulty_tracker.get = MagicMock(return_value=(tmp_difficulty, tmp_target))

        block_prev = state.get_block(genesis_block.headerhash)

        for block_idx in range(1, num_blocks):
            transactions = []
            if block_idx == 1:
                slave_tx = SlaveTransaction.create(slave_pks=[bob_xmss.pk],
                                                   access_types=[0],
                                                   fee=0,
                                                   xmss_pk=alice_xmss.pk)
                slave_tx.sign(alice_xmss)
                slave_tx._data.nonce = 2
                transactions = [slave_tx]

            time_mock.return_value = time_mock.return_value + 60
            ntp_mock.return_value = ntp_mock.return_value + 60

            block_new = Block.create(block_number=block_idx,
                                     prevblock_headerhash=block_prev.headerhash,
                                     transactions=transactions,
                                     miner_address=alice_xmss.address)

            while not PoWValidator().validate_mining_nonce(state, block_new.blockheader, False):
                block_new.set_nonces(block_new.mining_nonce + 1, 0)

            chain_manager.add_block(block_new)
            block_prev = block_new

        qrlnode = QRLNode(state, mining_credit_wallet=alice_xmss.address)
        qrlnode.set_chain_manager(chain_manager)

        yield qrlnode
Esempio n. 31
0
    def __init__(self, state):
        self.state = state
        self.tx_pool = TransactionPool()  # TODO: Move to some pool manager
        self.last_block = Block.from_json(GenesisBlock().to_json())
        self.current_difficulty = StringToUInt256(str(config.dev.genesis_difficulty))
        self._difficulty_tracker = DifficultyTracker()

        self.trigger_miner = False
Esempio n. 32
0
File: State.py Progetto: fanff/QRL
    def get_block(self, header_hash: bytes) -> Optional[Block]:
        try:
            json_data = self._db.get_raw(bin2hstr(header_hash).encode())
            return Block.from_json(json_data)
        except KeyError:
            logger.debug('[get_block] Block header_hash %s not found', bin2hstr(header_hash).encode())
        except Exception as e:
            logger.error('[get_block] %s', e)

        return None
Esempio n. 33
0
File: State.py Progetto: fanff/QRL
 def __init__(self, state_code, db: db.DB):
     self._db = db
     self.state_code = state_code
     if state_code != b'current_':
         json_data = self._db.get_raw(self.state_code)
         self._block_number = Block.from_json(json_data).block_number
     self._data = qrl_pb2.StateLoader()
     try:
         json_data = self._db.get_raw(b'state' + self.state_code)
         if json_data:
             Parse(json_data, self._data)
     except KeyError:
         pass
Esempio n. 34
0
File: main.py Progetto: fanff/QRL
def main():
    args = parse_arguments()

    config.create_path(config.user.wallet_dir)

    slaves = mining_wallet_checks(args)

    logger.debug("=====================================================================================")
    logger.info("Data Path: %s", args.data_dir)

    config.user.data_dir = args.data_dir
    config.create_path(config.user.data_dir)

    ntp.setDrift()

    logger.info('Initializing chain..')
    persistent_state = State()
    chain_manager = ChainManager(state=persistent_state)
    chain_manager.load(Block.from_json(GenesisBlock().to_json()))

    qrlnode = QRLNode(db_state=persistent_state, slaves=slaves)
    qrlnode.set_chain(chain_manager)

    set_logger(args, qrlnode.sync_state)

    #######
    # NOTE: Keep assigned to a variable or might get collected
    admin_service, grpc_service = start_services(qrlnode)

    qrlnode.start_listening()
    qrlnode.connect_peers()

    qrlnode.start_pow()

    logger.info('QRL blockchain ledger %s', config.dev.version)
    logger.info('mining/staking address %s', slaves[0])

    # FIXME: This will be removed once we move away from Twisted
    reactor.run()
Esempio n. 35
0
File: Miner.py Progetto: fanff/QRL
    def create_block(self, last_block, mining_nonce, tx_pool, signing_xmss, master_address) -> Optional[Block]:
        # TODO: Persistence will move to rocksdb
        # FIXME: Difference between this and create block?????????????

        # FIXME: Break encapsulation
        dummy_block = Block.create(mining_nonce=mining_nonce,
                                   block_number=last_block.block_number + 1,
                                   prevblock_headerhash=last_block.headerhash,
                                   transactions=[],
                                   signing_xmss=signing_xmss,
                                   master_address=master_address,
                                   nonce=0)
        dummy_block.set_mining_nonce(mining_nonce)
        signing_xmss.set_index(signing_xmss.get_index() - 1)

        t_pool2 = copy.deepcopy(tx_pool.transaction_pool)
        del tx_pool.transaction_pool[:]
        ######

        # recreate the transaction pool as in the tx_hash_list, ordered by txhash..
        total_txn = len(t_pool2)
        txnum = 0
        addresses_set = set()
        while txnum < total_txn:
            tx = t_pool2[txnum]
            tx.set_effected_address(addresses_set)
            txnum += 1

        addresses_state = dict()
        for address in addresses_set:
            addresses_state[address] = self.state.get_address(address)

        block_size = dummy_block.size
        block_size_limit = self.state.get_block_size_limit(last_block)
        txnum = 0
        while txnum < total_txn:
            tx = t_pool2[txnum]
            # Skip Transactions for later, which doesn't fit into block
            if block_size + tx.size + config.dev.tx_extra_overhead > block_size_limit:
                txnum += 1
                continue

            addr_from_pk_state = addresses_state[tx.txfrom]
            addr_from_pk = Transaction.get_slave(tx)
            if addr_from_pk:
                addr_from_pk_state = addresses_state[addr_from_pk]

            if tx.ots_key_reuse(addr_from_pk_state, tx.ots_key):
                del t_pool2[txnum]
                total_txn -= 1
                continue

            if tx.subtype == qrl_pb2.Transaction.TRANSFER:
                if addresses_state[tx.txfrom].balance < tx.amount + tx.fee:
                    logger.warning('%s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Transfer Amount %s', addresses_state[tx.txfrom].balance,
                                   tx.amount)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.MESSAGE:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('%s %s exceeds balance, invalid message tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Free %s', addresses_state[tx.txfrom].balance, tx.fee)
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.TOKEN:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('%s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Fee %s',
                                   addresses_state[tx.txfrom].balance,
                                   tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.TRANSFERTOKEN:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('%s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Transfer Amount %s',
                                   addresses_state[tx.txfrom].balance,
                                   tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

                if bin2hstr(tx.token_txhash).encode() not in addresses_state[tx.txfrom].tokens:
                    logger.warning('%s doesnt own any token with token_txnhash %s', tx.txfrom,
                                   bin2hstr(tx.token_txhash).encode())
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

                if addresses_state[tx.txfrom].tokens[bin2hstr(tx.token_txhash).encode()] < tx.amount:
                    logger.warning('Token Transfer amount exceeds available token')
                    logger.warning('Token Txhash %s', bin2hstr(tx.token_txhash).encode())
                    logger.warning('Available Token Amount %s',
                                   addresses_state[tx.txfrom].tokens[bin2hstr(tx.token_txhash).encode()])
                    logger.warning('Transaction Amount %s', tx.amount)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.LATTICE:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('Lattice TXN %s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Transfer Amount %s',
                                   addresses_state[tx.txfrom].balance,
                                   tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.SLAVE:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('Slave TXN %s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Transfer Amount %s',
                                   addresses_state[tx.txfrom].balance,
                                   tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            tx.apply_on_state(addresses_state)

            tx_pool.add_tx_to_pool(tx)
            tx._data.nonce = addresses_state[tx.txfrom].nonce
            txnum += 1
            block_size += tx.size + config.dev.tx_extra_overhead

        coinbase_nonce = self.state.get_address(signing_xmss.get_address()).nonce
        if signing_xmss.get_address() in addresses_state:
            coinbase_nonce = addresses_state[signing_xmss.get_address()].nonce + 1

        block = Block.create(mining_nonce=mining_nonce,
                             block_number=last_block.block_number + 1,
                             prevblock_headerhash=last_block.headerhash,
                             transactions=t_pool2,
                             signing_xmss=signing_xmss,
                             master_address=master_address,
                             nonce=coinbase_nonce)

        return block
Esempio n. 36
0
    def test_add_block(self):
        """
        Testing add_block, with fork logic
        :return:
        """
        with set_data_dir('no_data'):
            with State() as state:
                state.get_measurement = MagicMock(return_value=10000000)

                alice_xmss = get_alice_xmss()
                bob_xmss = get_bob_xmss()

                genesis_block = GenesisBlock()
                chain_manager = ChainManager(state)
                chain_manager.load(genesis_block)

                chain_manager._difficulty_tracker = Mock()
                dt = DifficultyTracker()
                tmp_difficulty = StringToUInt256('2')
                tmp_boundary = dt.get_boundary(tmp_difficulty)
                chain_manager._difficulty_tracker.get = MagicMock(return_value=(tmp_difficulty, tmp_boundary))

                block = state.get_block(genesis_block.headerhash)
                self.assertIsNotNone(block)

                slave_tx = SlaveTransaction.create(addr_from=alice_xmss.get_address(),
                                                   slave_pks=[bob_xmss.pk()],
                                                   access_types=[0],
                                                   fee=0,
                                                   xmss_pk=alice_xmss.pk(),
                                                   xmss_ots_index=alice_xmss.get_index())
                slave_tx.sign(alice_xmss)
                slave_tx._data.nonce = 2
                self.assertTrue(slave_tx.validate())
                with mock.patch('qrl.core.misc.ntp.getTime') as time_mock:
                    time_mock.return_value = 1615270948  # Very high to get an easy difficulty

                    block_1 = Block.create(mining_nonce=10,
                                           block_number=1,
                                           prevblock_headerhash=genesis_block.headerhash,
                                           transactions=[slave_tx],
                                           signing_xmss=alice_xmss,
                                           master_address=alice_xmss.get_address(),
                                           nonce=1)

                    while not chain_manager.validate_mining_nonce(block_1, False):
                        block_1.set_mining_nonce(block_1.mining_nonce + 1)

                    result = chain_manager.add_block(block_1)

                self.assertTrue(result)
                self.assertEqual(chain_manager.last_block, block_1)

                alice_state = chain_manager.get_address(alice_xmss.get_address())

                self.assertEqual(len(alice_state.slave_pks_access_type), 1)
                self.assertTrue(str(bob_xmss.pk()) in alice_state.slave_pks_access_type)

                with mock.patch('qrl.core.misc.ntp.getTime') as time_mock:
                    time_mock.return_value = 1715270948  # Very high to get an easy difficulty
                    block = Block.create(mining_nonce=15,
                                         block_number=1,
                                         prevblock_headerhash=genesis_block.headerhash,
                                         transactions=[],
                                         signing_xmss=bob_xmss,
                                         master_address=bob_xmss.get_address(),
                                         nonce=1)

                    while not chain_manager.validate_mining_nonce(block, False):
                        block.set_mining_nonce(block.mining_nonce + 1)

                    result = chain_manager.add_block(block)

                self.assertTrue(result)
                self.assertEqual(chain_manager.last_block, block_1)

                block = state.get_block(block.headerhash)
                self.assertIsNotNone(block)

                with mock.patch('qrl.core.misc.ntp.getTime') as time_mock:
                    time_mock.return_value = 1815270948  # Very high to get an easy difficulty
                    block_2 = Block.create(mining_nonce=15,
                                           block_number=2,
                                           prevblock_headerhash=block.headerhash,
                                           transactions=[],
                                           signing_xmss=bob_xmss,
                                           master_address=bob_xmss.get_address(),
                                           nonce=2)

                    while not chain_manager.validate_mining_nonce(block_2, False):
                        block_2.set_mining_nonce(block_2.mining_nonce + 1)

                    result = chain_manager.add_block(block_2)

                self.assertTrue(result)
                self.assertEqual(chain_manager.last_block.block_number, block_2.block_number)
                self.assertEqual(chain_manager.last_block.to_json(), block_2.to_json())
Esempio n. 37
0
    def test_orphan_block(self):
        """
        Testing add_block logic in case of orphan_blocks
        :return:
        """
        with mock.patch('qrl.core.config.DevConfig') as devconfig:
            devconfig.genesis_difficulty = 2
            devconfig.minimum_minting_delay = 10
            with set_data_dir('no_data'):
                with State() as state:  # FIXME: Move state to temporary directory
                    state.get_measurement = MagicMock(return_value=10000000)
                    genesis_block = GenesisBlock()

                    chain_manager = ChainManager(state)
                    chain_manager.load(genesis_block)

                    chain_manager._difficulty_tracker = Mock()
                    dt = DifficultyTracker()
                    tmp_difficulty = StringToUInt256('2')
                    tmp_boundary = dt.get_boundary(tmp_difficulty)
                    chain_manager._difficulty_tracker.get = MagicMock(return_value=(tmp_difficulty, tmp_boundary))

                    block = state.get_block(genesis_block.headerhash)
                    self.assertIsNotNone(block)
                    alice_xmss = get_alice_xmss()

                    with mock.patch('qrl.core.misc.ntp.getTime') as time_mock:
                        time_mock.return_value = 1615270948  # Very high to get an easy difficulty
                        block_1 = Block.create(mining_nonce=10,
                                               block_number=1,
                                               prevblock_headerhash=genesis_block.headerhash,
                                               transactions=[],
                                               signing_xmss=alice_xmss,
                                               master_address=alice_xmss.get_address(),
                                               nonce=1)
                        block_1.set_mining_nonce(10)

                        while not chain_manager.validate_mining_nonce(block_1, False):
                            block_1.set_mining_nonce(block_1.mining_nonce + 1)

                        result = chain_manager.add_block(block_1)

                    self.assertTrue(result)
                    self.assertEqual(chain_manager.last_block, block_1)

                    bob_xmss = get_bob_xmss()

                    with mock.patch('qrl.core.misc.ntp.getTime') as time_mock:
                        time_mock.return_value = 1615270948 + devconfig.minimum_minting_delay * 2
                        block = Block.create(mining_nonce=18,
                                             block_number=1,
                                             prevblock_headerhash=genesis_block.headerhash,
                                             transactions=[],
                                             signing_xmss=bob_xmss,
                                             master_address=bob_xmss.get_address(),
                                             nonce=1)
                        block.set_mining_nonce(18)

                        while not chain_manager.validate_mining_nonce(block, False):
                            block.set_mining_nonce(block.mining_nonce + 1)

                    with mock.patch('qrl.core.misc.ntp.getTime') as time_mock:
                        time_mock.return_value = 1615270948 + devconfig.minimum_minting_delay * 3
                        block_2 = Block.create(mining_nonce=17,
                                               block_number=2,
                                               prevblock_headerhash=block.headerhash,
                                               transactions=[],
                                               signing_xmss=bob_xmss,
                                               master_address=bob_xmss.get_address(),
                                               nonce=2)
                        block_2.set_mining_nonce(17)

                    result = chain_manager.add_block(block_2)
                    self.assertTrue(result)

                    result = chain_manager.add_block(block)
                    self.assertTrue(result)

                    block = state.get_block(block.headerhash)
                    self.assertIsNotNone(block)

                    self.assertEqual(chain_manager.last_block.block_number, block_1.block_number)
                    self.assertEqual(chain_manager.last_block.headerhash, block_1.headerhash)