コード例 #1
0
ファイル: MockedBlockchain.py プロジェクト: kstuart/QRL
    def create(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)

            genesis_difficulty = config.dev.genesis_difficulty
            try:
                config.dev.genesis_difficulty = 10
                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))

                qrlnode = QRLNode(state, mining_credit_wallet=b'')
                qrlnode.set_chain_manager(chain_manager)

                mock_blockchain = MockedBlockchain(qrlnode, time_mock, ntp_mock, )
                for block_idx in range(1, num_blocks + 1):
                    mock_blockchain.add_new_block()

                yield mock_blockchain
            finally:
                config.dev.genesis_difficulty = genesis_difficulty
コード例 #2
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
コード例 #3
0
ファイル: ChainManager.py プロジェクト: scottdonaldau/QRL
    def _add_block_metadata(self, headerhash, block_timestamp,
                            parent_headerhash, batch):
        block_metadata = self._state.get_block_metadata(headerhash)
        if not block_metadata:
            block_metadata = BlockMetadata.create()

        parent_metadata = self._state.get_block_metadata(parent_headerhash)

        parent_block_difficulty = parent_metadata.block_difficulty
        parent_cumulative_difficulty = parent_metadata.cumulative_difficulty

        block_metadata.update_last_headerhashes(
            parent_metadata.last_N_headerhashes, parent_headerhash)
        measurement = self._state.get_measurement(block_timestamp,
                                                  parent_headerhash,
                                                  parent_metadata)

        block_difficulty, _ = DifficultyTracker.get(
            measurement=measurement, parent_difficulty=parent_block_difficulty)

        block_cumulative_difficulty = StringToUInt256(
            str(
                int(UInt256ToString(block_difficulty)) +
                int(UInt256ToString(parent_cumulative_difficulty))))

        block_metadata.set_block_difficulty(block_difficulty)
        block_metadata.set_cumulative_difficulty(block_cumulative_difficulty)

        parent_metadata.add_child_headerhash(headerhash)
        self._state.put_block_metadata(parent_headerhash, parent_metadata,
                                       batch)
        self._state.put_block_metadata(headerhash, block_metadata, batch)

        return block_metadata
コード例 #4
0
ファイル: ChainManager.py プロジェクト: som-dev/QRL
    def validate_mining_nonce(self, block, enable_logging=False):
        parent_metadata = self.state.get_block_metadata(block.prev_headerhash)
        parent_block = self.state.get_block(block.prev_headerhash)

        measurement = self.state.get_measurement(block.timestamp,
                                                 block.prev_headerhash,
                                                 parent_metadata)
        diff, target = DifficultyTracker.get(
            measurement=measurement,
            parent_difficulty=parent_metadata.block_difficulty)

        if enable_logging:
            logger.debug('-----------------START--------------------')
            logger.debug('Validate #%s', block.block_number)
            logger.debug('block.timestamp %s', block.timestamp)
            logger.debug('parent_block.timestamp %s', parent_block.timestamp)
            logger.debug('parent_block.difficulty %s',
                         UInt256ToString(parent_metadata.block_difficulty))
            logger.debug('diff : %s | target : %s', UInt256ToString(diff),
                         target)
            logger.debug('-------------------END--------------------')

        if not self.verify_input_cached(block.mining_blob, target):
            if enable_logging:
                logger.warning("PoW verification failed")
                qn = Qryptonight()
                tmp_hash = qn.hash(block.mining_blob)
                logger.warning("{}".format(tmp_hash))
                logger.debug('%s', block.to_json())
            return False

        return True
コード例 #5
0
    def prepare_next_unmined_block_template(self, tx_pool, parent_block: Block,
                                            parent_difficulty):
        mining_xmss = self.get_mining_xmss()
        if not mining_xmss:
            logger.warning('No Mining XMSS Found')
            return

        try:
            self.cancel()
            self._mining_block = self.create_block(
                last_block=parent_block,
                mining_nonce=0,
                tx_pool=tx_pool,
                signing_xmss=self._mining_xmss,
                master_address=self._master_address)

            parent_metadata = self.state.get_block_metadata(
                parent_block.headerhash)
            self._measurement = self.state.get_measurement(
                self._mining_block.timestamp,
                self._mining_block.prev_headerhash, parent_metadata)

            self._current_difficulty, self._current_target = DifficultyTracker.get(
                measurement=self._measurement,
                parent_difficulty=parent_difficulty)

        except Exception as e:
            logger.warning("Exception in start_mining")
            logger.exception(e)
コード例 #6
0
    def prepare_next_unmined_block_template(self,
                                            mining_address,
                                            tx_pool,
                                            parent_block: Block,
                                            parent_difficulty,
                                            dev_config: DevConfig):
        miner = self.get_miner(parent_block.block_number + 1, dev_config)
        try:
            logger.debug('Miner-Try - prepare_next_unmined_block_template')
            with self.lock:
                logger.debug('Miner-Locked - prepare_next_unmined_block_template')

                logger.debug('Miner-TryCancel - prepare_next_unmined_block_template')
                miner.cancel()
                logger.debug('Miner-Cancel - prepare_next_unmined_block_template')

                self._mining_block = self.create_block(last_block=parent_block,
                                                       mining_nonce=0,
                                                       tx_pool=tx_pool,
                                                       miner_address=mining_address)

                parent_metadata = self._chain_manager.get_block_metadata(parent_block.headerhash)
                self._measurement = self._chain_manager.get_measurement(dev_config,
                                                                        self._mining_block.timestamp,
                                                                        self._mining_block.prev_headerhash,
                                                                        parent_metadata)

                self._current_difficulty, self._current_target = DifficultyTracker.get(
                    measurement=self._measurement,
                    parent_difficulty=parent_difficulty,
                    dev_config=dev_config)

        except Exception as e:
            logger.warning("Exception in start_mining")
            logger.exception(e)
コード例 #7
0
    def load(self, genesis_block):
        height = self.state.get_mainchain_height()

        if height == -1:
            self.state.put_block(genesis_block, None)
            block_number_mapping = qrl_pb2.BlockNumberMapping(headerhash=genesis_block.headerhash,
                                                              prev_headerhash=genesis_block.prev_headerhash)

            self.state.put_block_number_mapping(genesis_block.block_number, block_number_mapping, None)
            parent_difficulty = StringToUInt256(str(config.dev.genesis_difficulty))

            self.current_difficulty, _ = DifficultyTracker.get(
                measurement=config.dev.mining_setpoint_blocktime,
                parent_difficulty=parent_difficulty)

            block_metadata = BlockMetadata.create()

            block_metadata.set_orphan(False)
            block_metadata.set_block_difficulty(self.current_difficulty)
            block_metadata.set_cumulative_difficulty(self.current_difficulty)

            self.state.put_block_metadata(genesis_block.headerhash, block_metadata, None)
            addresses_state = dict()
            for genesis_balance in GenesisBlock().genesis_balance:
                bytes_addr = genesis_balance.address
                addresses_state[bytes_addr] = AddressState.get_default(bytes_addr)
                addresses_state[bytes_addr]._data.balance = genesis_balance.balance
            self.state.state_objects.update_current_state(addresses_state)
            self.state.state_objects.push(genesis_block.headerhash)
        else:
            self.last_block = self.get_block_by_number(height)
            self.current_difficulty = self.state.get_block_metadata(self.last_block.headerhash).block_difficulty
コード例 #8
0
ファイル: ChainManager.py プロジェクト: fanff/QRL
    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
コード例 #9
0
ファイル: Miner.py プロジェクト: fanff/QRL
 def __init__(self, pre_block_logic, slaves: list, state: State, add_unprocessed_txn_fn):
     super().__init__()
     self.pre_block_logic = pre_block_logic  # FIXME: Circular dependency with node.py
     self._mining_block = None
     self._slaves = slaves
     self._mining_xmss = None
     self._reward_address = None
     self.state = state
     self._difficulty_tracker = DifficultyTracker()
     self._add_unprocessed_txn_fn = add_unprocessed_txn_fn
コード例 #10
0
ファイル: ChainManager.py プロジェクト: amitkumarj441/QRL
    def load(self, genesis_block):
        height = self.state.get_mainchain_height()

        if height == -1:
            self.state.put_block(genesis_block, None)
            block_number_mapping = qrl_pb2.BlockNumberMapping(headerhash=genesis_block.headerhash,
                                                              prev_headerhash=genesis_block.prev_headerhash)

            self.state.put_block_number_mapping(genesis_block.block_number, block_number_mapping, None)
            parent_difficulty = StringToUInt256(str(config.dev.genesis_difficulty))

            self.current_difficulty, _ = DifficultyTracker.get(
                measurement=config.dev.mining_setpoint_blocktime,
                parent_difficulty=parent_difficulty)

            block_metadata = BlockMetadata.create()

            block_metadata.set_orphan(False)
            block_metadata.set_block_difficulty(self.current_difficulty)
            block_metadata.set_cumulative_difficulty(self.current_difficulty)

            self.state.put_block_metadata(genesis_block.headerhash, block_metadata, None)
            addresses_state = dict()
            for genesis_balance in GenesisBlock().genesis_balance:
                bytes_addr = genesis_balance.address
                addresses_state[bytes_addr] = AddressState.get_default(bytes_addr)
                addresses_state[bytes_addr]._data.balance = genesis_balance.balance

            for tx_idx in range(1, len(genesis_block.transactions)):
                tx = Transaction.from_pbdata(genesis_block.transactions[tx_idx])
                for addr in tx.addrs_to:
                    addresses_state[addr] = AddressState.get_default(addr)

            coinbase_tx = Transaction.from_pbdata(genesis_block.transactions[0])

            if not isinstance(coinbase_tx, CoinBase):
                return False

            addresses_state[coinbase_tx.addr_to] = AddressState.get_default(coinbase_tx.addr_to)

            if not coinbase_tx.validate_extended():
                return False

            coinbase_tx.apply_on_state(addresses_state)

            for tx_idx in range(1, len(genesis_block.transactions)):
                tx = Transaction.from_pbdata(genesis_block.transactions[tx_idx])
                tx.apply_on_state(addresses_state)

            self.state.state_objects.update_current_state(addresses_state)
            self.state.state_objects.update_tx_metadata(genesis_block, None)
            self.state.state_objects.push(genesis_block.headerhash)
        else:
            self.last_block = self.get_block_by_number(height)
            self.current_difficulty = self.state.get_block_metadata(self.last_block.headerhash).block_difficulty
コード例 #11
0
    def test_simple_add_block(self):
        with set_data_dir('no_data'):
            with State() as state:
                state.get_measurement = MagicMock(return_value=10000000)
                alice_xmss = get_alice_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 = state.get_block(genesis_block.headerhash)
                self.assertIsNotNone(block)

                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(
                        block_number=1,
                        prevblock_headerhash=genesis_block.headerhash,
                        transactions=[],
                        miner_address=alice_xmss.address)
                    block_1.set_nonces(491, 0)
                    from pyqrllib.pyqrllib import bin2hstr
                    print(bin2hstr(block.headerhash))
                    # Uncomment only to determine the correct mining_nonce of above blocks
                    # from qrl.core.PoWValidator import PoWValidator
                    # while not PoWValidator().validate_mining_nonce(state, block_1.blockheader, False):
                    #     block_1.set_nonces(block_1.mining_nonce + 1)
                    #     print(block_1.mining_nonce)

                    result = chain_manager.add_block(block_1)

                self.assertTrue(result)
                self.assertEqual(chain_manager.last_block, block_1)
コード例 #12
0
ファイル: test_ChainManager.py プロジェクト: nerdy-dad/QRL
    def test_simple_add_block(self):
        with set_data_dir('no_data'):
            with State() as state:
                state.get_measurement = MagicMock(return_value=10000000)
                alice_xmss = get_alice_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_target(tmp_difficulty)
                chain_manager._difficulty_tracker.get = MagicMock(
                    return_value=(tmp_difficulty, tmp_boundary))

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

                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(
                        block_number=1,
                        prevblock_headerhash=genesis_block.headerhash,
                        transactions=[],
                        signing_xmss=alice_xmss,
                        master_address=alice_xmss.address,
                        nonce=1)

                    while not PoWValidator().validate_mining_nonce(
                            state, block_1.blockheader, 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)
コード例 #13
0
ファイル: ChainManager.py プロジェクト: som-dev/QRL
    def add_block_metadata(self, headerhash, block_timestamp,
                           parent_headerhash, batch):
        block_metadata = self.state.get_block_metadata(headerhash)
        if not block_metadata:
            block_metadata = BlockMetadata.create()

        parent_metadata = self.state.get_block_metadata(parent_headerhash)
        block_difficulty = (0, ) * 32  # 32 bytes to represent 256 bit of 0
        block_cumulative_difficulty = (
            0, ) * 32  # 32 bytes to represent 256 bit of 0
        if not parent_metadata:
            parent_metadata = BlockMetadata.create()
        else:
            parent_block = self.state.get_block(parent_headerhash)
            if parent_block:
                parent_block_difficulty = parent_metadata.block_difficulty
                parent_cumulative_difficulty = parent_metadata.cumulative_difficulty

                if not parent_metadata.is_orphan:
                    block_metadata.update_last_headerhashes(
                        parent_metadata.last_N_headerhashes, parent_headerhash)
                    measurement = self.state.get_measurement(
                        block_timestamp, parent_headerhash, parent_metadata)

                    block_difficulty, _ = DifficultyTracker.get(
                        measurement=measurement,
                        parent_difficulty=parent_block_difficulty)

                    block_cumulative_difficulty = StringToUInt256(
                        str(
                            int(UInt256ToString(block_difficulty)) +
                            int(UInt256ToString(parent_cumulative_difficulty)))
                    )

        block_metadata.set_orphan(parent_metadata.is_orphan)
        block_metadata.set_block_difficulty(block_difficulty)
        block_metadata.set_cumulative_difficulty(block_cumulative_difficulty)

        parent_metadata.add_child_headerhash(headerhash)
        self.state.put_block_metadata(parent_headerhash, parent_metadata,
                                      batch)
        self.state.put_block_metadata(headerhash, block_metadata, batch)

        # Call once to populate the cache
        self.state.get_block_datapoint(headerhash)
コード例 #14
0
ファイル: Miner.py プロジェクト: amitkumarj441/QRL
    def prepare_next_unmined_block_template(self, tx_pool, parent_block: Block, parent_difficulty):
        try:
            self.cancel()
            self._mining_block = self.create_block(last_block=parent_block,
                                                   mining_nonce=0,
                                                   tx_pool=tx_pool,
                                                   miner_address=self._mining_credit_wallet)

            parent_metadata = self.state.get_block_metadata(parent_block.headerhash)
            self._measurement = self.state.get_measurement(self._mining_block.timestamp,
                                                           self._mining_block.prev_headerhash,
                                                           parent_metadata)

            self._current_difficulty, self._current_target = DifficultyTracker.get(
                measurement=self._measurement,
                parent_difficulty=parent_difficulty)

        except Exception as e:
            logger.warning("Exception in start_mining")
            logger.exception(e)
コード例 #15
0
ファイル: ChainManager.py プロジェクト: scottdonaldau/QRL
    def validate_mining_nonce(self,
                              blockheader: BlockHeader,
                              enable_logging=True):
        with self.lock:
            parent_metadata = self.get_block_metadata(
                blockheader.prev_headerhash)
            parent_block = self._state.get_block(blockheader.prev_headerhash)

            measurement = self.get_measurement(blockheader.timestamp,
                                               blockheader.prev_headerhash,
                                               parent_metadata)
            diff, target = DifficultyTracker.get(
                measurement=measurement,
                parent_difficulty=parent_metadata.block_difficulty)

            if enable_logging:
                logger.debug('-----------------START--------------------')
                logger.debug('Validate                #%s',
                             blockheader.block_number)
                logger.debug('block.timestamp         %s',
                             blockheader.timestamp)
                logger.debug('parent_block.timestamp  %s',
                             parent_block.timestamp)
                logger.debug('parent_block.difficulty %s',
                             UInt256ToString(parent_metadata.block_difficulty))
                logger.debug('diff                    %s',
                             UInt256ToString(diff))
                logger.debug('target                  %s', bin2hstr(target))
                logger.debug('-------------------END--------------------')

            if not PoWValidator().verify_input(blockheader.mining_blob,
                                               target):
                if enable_logging:
                    logger.warning("PoW verification failed")
                    qn = Qryptonight()
                    tmp_hash = qn.hash(blockheader.mining_blob)
                    logger.warning("{}".format(bin2hstr(tmp_hash)))
                    logger.debug('%s', blockheader.to_json())
                return False

            return True
コード例 #16
0
ファイル: test_ChainManager.py プロジェクト: fanff/QRL
    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())
コード例 #17
0
ファイル: ChainManager.py プロジェクト: fanff/QRL
class ChainManager:
    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

    @property
    def height(self):
        return self.last_block.block_number

    def get_last_block(self) -> Block:
        return self.last_block

    def get_cumulative_difficulty(self):
        last_block_metadata = self.state.get_block_metadata(self.last_block.headerhash)
        return last_block_metadata.cumulative_difficulty

    def load(self, genesis_block):
        height = self.state.get_mainchain_height()

        if height == -1:
            self.state.put_block(genesis_block, None)
            block_number_mapping = qrl_pb2.BlockNumberMapping(headerhash=genesis_block.headerhash,
                                                              prev_headerhash=genesis_block.prev_headerhash)

            self.state.put_block_number_mapping(genesis_block.block_number, block_number_mapping, None)
            parent_difficulty = StringToUInt256(str(config.dev.genesis_difficulty))

            self.current_difficulty, _ = self._difficulty_tracker.get(
                measurement=config.dev.mining_setpoint_blocktime,
                parent_difficulty=parent_difficulty)

            block_metadata = BlockMetadata.create()

            block_metadata.set_orphan(False)
            block_metadata.set_block_difficulty(self.current_difficulty)
            block_metadata.set_cumulative_difficulty(self.current_difficulty)

            self.state.put_block_metadata(genesis_block.headerhash, block_metadata, None)
            addresses_state = dict()
            for genesis_balance in GenesisBlock().genesis_balance:
                bytes_addr = genesis_balance.address.encode()
                addresses_state[bytes_addr] = AddressState.get_default(bytes_addr)
                addresses_state[bytes_addr]._data.balance = genesis_balance.balance
            self.state.state_objects.update_current_state(addresses_state)
            self.state.state_objects.push(genesis_block.headerhash)
        else:
            self.last_block = self.get_block_by_number(height)
            self.current_difficulty = self.state.get_block_metadata(self.last_block.headerhash).block_difficulty

    def validate_mining_nonce(self, block, enable_logging=False):
        parent_metadata = self.state.get_block_metadata(block.prev_headerhash)
        parent_block = self.state.get_block(block.prev_headerhash)
        input_bytes = StringToUInt256(str(block.mining_nonce))[-4:] + tuple(block.mining_hash)

        measurement = self.state.get_measurement(block.timestamp, block.prev_headerhash)
        diff, target = self._difficulty_tracker.get(
            measurement=measurement,
            parent_difficulty=parent_metadata.block_difficulty)

        if enable_logging:
            logger.debug('-----------------START--------------------')
            logger.debug('Validate #%s', block.block_number)
            logger.debug('block.timestamp %s', block.timestamp)
            logger.debug('parent_block.timestamp %s', parent_block.timestamp)
            logger.debug('parent_block.difficulty %s', UInt256ToString(parent_metadata.block_difficulty))
            logger.debug('input_bytes %s', UInt256ToString(input_bytes))
            logger.debug('diff : %s | target : %s', UInt256ToString(diff), target)
            logger.debug('-------------------END--------------------')

        if not PoWHelper.verifyInput(input_bytes, target):
            if enable_logging:
                logger.warning("PoW verification failed")
                qn = Qryptonight()
                tmp_hash = qn.hash(input_bytes)
                logger.warning("{}".format(tmp_hash))
                logger.debug('%s', block.to_json())
            return False

        return True

    def validate_block(self, block, address_txn) -> bool:
        len_transactions = len(block.transactions)

        if len_transactions < 1:
            return False

        coinbase_tx = Transaction.from_pbdata(block.transactions[0])
        coinbase_tx.validate()

        if not self.validate_mining_nonce(block):
            return False

        if coinbase_tx.subtype != qrl_pb2.Transaction.COINBASE:
            return False

        if not coinbase_tx.validate():
            return False

        coinbase_tx.apply_on_state(address_txn)

        addr_from_pk_state = address_txn[coinbase_tx.txto]
        addr_from_pk = Transaction.get_slave(coinbase_tx)
        if addr_from_pk:
            addr_from_pk_state = address_txn[addr_from_pk]

        if not coinbase_tx.validate_extended(address_txn[coinbase_tx.txto],
                                             addr_from_pk_state,
                                             []):
            return False

        # TODO: check block reward must be equal to coinbase amount

        for tx_idx in range(1, len_transactions):
            tx = Transaction.from_pbdata(block.transactions[tx_idx])

            if tx.subtype == qrl_pb2.Transaction.COINBASE:
                return False

            if not tx.validate():  # TODO: Move this validation, before adding txn to pool
                return False

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

            if not tx.validate_extended(address_txn[tx.txfrom], addr_from_pk_state, []):
                return False

            expected_nonce = address_txn[tx.txfrom].nonce + 1

            if tx.nonce != expected_nonce:
                logger.warning('nonce incorrect, invalid tx')
                logger.warning('subtype: %s', tx.subtype)
                logger.warning('%s actual: %s expected: %s', tx.txfrom, tx.nonce, expected_nonce)
                return False

            if tx.ots_key_reuse(address_txn[tx.txfrom], tx.ots_key):
                logger.warning('pubkey reuse detected: invalid tx %s', tx.txhash)
                logger.warning('subtype: %s', tx.subtype)
                return False

            tx.apply_on_state(address_txn)

        return True

    def _pre_check(self, block, ignore_duplicate):
        if block.block_number < 1:
            return False

        if not block.validate():
            return False

        if (not ignore_duplicate) and self.state.get_block(block.headerhash):  # Duplicate block check
            logger.info('Duplicate block %s %s', block.block_number, bin2hstr(block.headerhash))
            return False

        return True

    def _try_orphan_add_block(self, block, batch):
        prev_block_metadata = self.state.get_block_metadata(block.prev_headerhash)

        self.trigger_miner = False

        if prev_block_metadata is None or prev_block_metadata.is_orphan:
            self.state.put_block(block, batch)
            self.add_block_metadata(block.headerhash, block.timestamp, block.prev_headerhash, batch)
            return True

        return False

    def _try_branch_add_block(self, block, batch=None) -> bool:
        parent_block = self.state.get_block(block.prev_headerhash)
        if not block.validate_parent_child_relation(parent_block):
            logger.warning('Failed to validate blocks parent child relation')
            return False

        address_set = self.state.prepare_address_list(block)  # Prepare list for current block
        if self.last_block.headerhash == block.prev_headerhash:
            address_txn = self.state.get_state_mainchain(address_set)
        else:
            address_txn = self.state.get_state(block.prev_headerhash, address_set)

        if self.validate_block(block, address_txn):
            self.state.put_block(block, None)
            self.add_block_metadata(block.headerhash, block.timestamp, block.prev_headerhash, None)

            last_block_metadata = self.state.get_block_metadata(self.last_block.headerhash)
            new_block_metadata = self.state.get_block_metadata(block.headerhash)
            last_block_difficulty = int(UInt256ToString(last_block_metadata.cumulative_difficulty))
            new_block_difficulty = int(UInt256ToString(new_block_metadata.cumulative_difficulty))

            self.trigger_miner = False
            if new_block_difficulty > last_block_difficulty:
                if self.last_block.headerhash != block.prev_headerhash:
                    self.rollback(block)
                    return True

                self.state.update_mainchain_state(address_txn, block.block_number, block.headerhash)
                self.last_block = block
                self._update_mainchain(block, batch)
                self.tx_pool.remove_tx_in_block_from_pool(block)
                self.state.update_mainchain_height(block.block_number, batch)
                self.state.update_tx_metadata(block, batch)

                self.trigger_miner = True

            return True

        return False

    def rollback(self, block):
        hash_path = []
        while True:
            if self.state.state_objects.contains(block.headerhash):
                break
            hash_path.append(block.headerhash)
            new_block = self.state.get_block(block.prev_headerhash)
            if not new_block:
                logger.warning('No block found %s', block.prev_headerhash)
                break
            block = new_block
            if block.block_number == 0:
                del hash_path[-1]  # Skip replaying Genesis Block
                break

        self.state.state_objects.destroy_current_state(None)
        block = self.state.get_block(hash_path[-1])
        self.state.state_objects.destroy_fork_states(block.block_number, block.headerhash)

        for header_hash in hash_path[-1::-1]:
            block = self.state.get_block(header_hash)
            address_set = self.state.prepare_address_list(block)  # Prepare list for current block
            address_txn = self.state.get_state_mainchain(address_set)

            self.state.update_mainchain_state(address_txn, block.block_number, block.headerhash)
            self.last_block = block
            self._update_mainchain(block, None)
            self.tx_pool.remove_tx_in_block_from_pool(block)
            self.state.update_mainchain_height(block.block_number, None)
            self.state.update_tx_metadata(block, None)

        self.trigger_miner = True

    def _add_block(self, block, ignore_duplicate=False, batch=None):
        block_size_limit = self.state.get_block_size_limit(block)
        if block_size_limit and block.size > block_size_limit:
            logger.info('Block Size greater than threshold limit %s > %s', block.size, block_size_limit)
            return False

        if not self._pre_check(block, ignore_duplicate):
            logger.debug('Failed pre_check')
            return False

        if self._try_orphan_add_block(block, batch):
            return True

        if self._try_branch_add_block(block, batch):
            return True

        return False

    def add_block(self, block: Block) -> bool:
        if block.block_number < self.height - config.dev.reorg_limit:
            logger.debug('Skipping block #%s as beyond re-org limit', block.block_number)
            return False

        batch = self.state.get_batch()
        if self._add_block(block, batch=batch):
            self.state.write_batch(batch)
            self.update_child_metadata(block.headerhash)
            return True

        return False

    def update_child_metadata(self, headerhash):
        block_metadata = self.state.get_block_metadata(headerhash)

        childs = list(block_metadata.child_headerhashes)

        while childs:
            child_headerhash = childs.pop(0)
            block = self.state.get_block(child_headerhash)
            if not block:
                continue
            if not self._add_block(block, True):
                self._prune([block.headerhash], None)
                continue
            block_metadata = self.state.get_block_metadata(child_headerhash)
            childs += block_metadata.child_headerhashes

    def _prune(self, childs, batch):
        while childs:
            child_headerhash = childs.pop(0)

            block_metadata = self.state.get_block_metadata(child_headerhash)
            childs += block_metadata.child_headerhashes

            self.state.delete(bin2hstr(child_headerhash).encode(), batch)
            self.state.delete(b'metadata_' + bin2hstr(child_headerhash).encode(), batch)

    def add_block_metadata(self,
                           headerhash,
                           block_timestamp,
                           parent_headerhash,
                           batch):
        parent_metadata = self.state.get_block_metadata(parent_headerhash)
        block_difficulty = (0,) * 32  # 32 bytes to represent 256 bit of 0
        block_cumulative_difficulty = (0,) * 32  # 32 bytes to represent 256 bit of 0
        if not parent_metadata:
            parent_metadata = BlockMetadata.create()
        else:
            parent_block = self.state.get_block(parent_headerhash)
            if parent_block:
                parent_block_difficulty = parent_metadata.block_difficulty
                parent_cumulative_difficulty = parent_metadata.cumulative_difficulty

                if not parent_metadata.is_orphan:
                    measurement = self.state.get_measurement(block_timestamp, parent_headerhash)

                    block_difficulty, _ = self._difficulty_tracker.get(
                        measurement=measurement,
                        parent_difficulty=parent_block_difficulty)

                    block_cumulative_difficulty = StringToUInt256(str(
                        int(UInt256ToString(block_difficulty)) +
                        int(UInt256ToString(parent_cumulative_difficulty))))

        block_metadata = self.state.get_block_metadata(headerhash)
        if not block_metadata:
            block_metadata = BlockMetadata.create()

        block_metadata.set_orphan(parent_metadata.is_orphan)
        block_metadata.set_block_difficulty(block_difficulty)
        block_metadata.set_cumulative_difficulty(block_cumulative_difficulty)
        parent_metadata.add_child_headerhash(headerhash)
        self.state.put_block_metadata(parent_headerhash, parent_metadata, batch)
        self.state.put_block_metadata(headerhash, block_metadata, batch)

    def _update_mainchain(self, block, batch):
        measurement = self.state.get_measurement(block.timestamp, block.prev_headerhash)

        self.current_difficulty, _ = self._difficulty_tracker.get(
            measurement=measurement,
            parent_difficulty=self.current_difficulty)

        block_number_mapping = None
        while block_number_mapping is None or block.headerhash != block_number_mapping.headerhash:
            block_number_mapping = qrl_pb2.BlockNumberMapping(headerhash=block.headerhash,
                                                              prev_headerhash=block.prev_headerhash)
            self.state.put_block_number_mapping(block.block_number, block_number_mapping, batch)
            block = self.state.get_block(block.prev_headerhash)
            block_number_mapping = self.state.get_block_number_mapping(block.block_number)

    def get_block_by_number(self, block_number) -> Optional[Block]:
        return self.state.get_block_by_number(block_number)

    def get_state(self, headerhash):
        return self.state.get_state(headerhash, set())

    def get_address(self, address):
        return self.state.get_address(address)

    def get_transaction(self, transaction_hash) -> list:
        for tx in self.tx_pool.transaction_pool:
            if tx.txhash == transaction_hash:
                return [tx, None]

        return self.state.get_tx_metadata(transaction_hash)

    def get_headerhashes(self, start_blocknumber):
        start_blocknumber = max(0, start_blocknumber)
        end_blocknumber = min(self.last_block.block_number,
                              start_blocknumber + config.dev.reorg_limit)

        node_header_hash = qrl_pb2.NodeHeaderHash()
        node_header_hash.block_number = start_blocknumber

        for i in range(start_blocknumber, end_blocknumber + 1):
            block = self.state.get_block_by_number(i)
            node_header_hash.headerhashes.append(block.headerhash)

        return node_header_hash

    def add_ephemeral_message(self, encrypted_ephemeral: EncryptedEphemeralMessage):
        self.state.update_ephemeral(encrypted_ephemeral)
コード例 #18
0
    def test_multi_output_transaction_add_block(self):
        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()
                extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \
                                "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c"
                random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed))

                transfer_transaction = TransferTransaction.create(
                    addrs_to=[alice_xmss.address, random_xmss.address],
                    amounts=[
                        40 * int(config.dev.shor_per_quanta),
                        59 * int(config.dev.shor_per_quanta)
                    ],
                    fee=1 * config.dev.shor_per_quanta,
                    xmss_pk=bob_xmss.pk)
                transfer_transaction._data.nonce = 1
                transfer_transaction.sign(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_target(tmp_difficulty)
                chain_manager._difficulty_tracker.get = MagicMock(
                    return_value=(tmp_difficulty, tmp_boundary))

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

                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(
                        block_number=1,
                        prevblock_headerhash=genesis_block.headerhash,
                        transactions=[transfer_transaction],
                        miner_address=alice_xmss.address)
                    block_1.set_nonces(274, 0)

                    # Uncomment only to determine the correct mining_nonce of above blocks
                    # from qrl.core.PoWValidator import PoWValidator
                    # while not PoWValidator().validate_mining_nonce(state, block_1.blockheader, False):
                    #     block_1.set_nonces(block_1.mining_nonce + 1)
                    #     print(block_1.mining_nonce)

                    result = chain_manager.add_block(block_1)

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

                bob_addr_state = state.get_address(bob_xmss.address)
                alice_addr_state = state.get_address(alice_xmss.address)
                random_addr_state = state.get_address(random_xmss.address)

                self.assertEqual(bob_addr_state.balance, 0)
                self.assertEqual(
                    alice_addr_state.balance,
                    140 * int(config.dev.shor_per_quanta) +
                    block_1.block_reward + block_1.fee_reward)
                self.assertEqual(random_addr_state.balance,
                                 159 * int(config.dev.shor_per_quanta))
コード例 #19
0
    def test_add_block(self, mock_difficulty_tracker_get):
        """
        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)
                mock_difficulty_tracker_get.return_value = [
                    config.dev.mining_setpoint_blocktime, 2
                ]
                chain_manager.load(genesis_block)

                chain_manager._difficulty_tracker = Mock()
                tmp_difficulty = StringToUInt256('2')
                tmp_target = DifficultyTracker.get_target(tmp_difficulty)
                mock_difficulty_tracker_get.return_value = [
                    tmp_difficulty, tmp_target
                ]

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

                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 = 1
                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(
                        block_number=1,
                        prevblock_headerhash=genesis_block.headerhash,
                        transactions=[slave_tx],
                        miner_address=alice_xmss.address)
                    block_1.set_nonces(274, 0)
                    # Uncomment only to determine the correct mining_nonce of above blocks
                    # from qrl.core.PoWValidator import PoWValidator
                    # while not PoWValidator().validate_mining_nonce(state, block_1.blockheader, False):
                    #     block_1.set_mining_nonce(block_1.mining_nonce + 1)
                    #     print(block_1.mining_nonce)
                    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.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(
                        block_number=1,
                        prevblock_headerhash=genesis_block.headerhash,
                        transactions=[],
                        miner_address=bob_xmss.address)

                    block.set_nonces(2, 0)
                    # Uncomment only to determine the correct mining_nonce of above blocks
                    # from qrl.core.PoWValidator import PoWValidator
                    # while not PoWValidator().validate_mining_nonce(state, block.blockheader, False):
                    #     block.set_nonces(block.mining_nonce + 1)
                    #     print(block.mining_nonce)
                    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(
                        block_number=2,
                        prevblock_headerhash=block.headerhash,
                        transactions=[],
                        miner_address=bob_xmss.address)

                    block_2.set_nonces(0, 0)
                    # Uncomment only to determine the correct mining_nonce of above blocks
                    # from qrl.core.PoWValidator import PoWValidator
                    # while not PoWValidator().validate_mining_nonce(state, block_2.blockheader, False):
                    #     block_2.set_mining_nonce(block_2.mining_nonce + 1)
                    #     print(block_2.mining_nonce)
                    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())
コード例 #20
0
    def test_orphan_block(self):
        """
        Testing add_block logic in case of orphan_blocks.
        This test is expected to shift the mainchain towards block_2.
        :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_target = dt.get_target(tmp_difficulty)
                    chain_manager._difficulty_tracker.get = MagicMock(
                        return_value=(tmp_difficulty, tmp_target))

                    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 = 1521889325  # Very high to get an easy difficulty
                        block_1 = Block.create(
                            block_number=1,
                            prevblock_headerhash=genesis_block.headerhash,
                            transactions=[],
                            miner_address=alice_xmss.address)
                        block_1.set_nonces(29, 0)
                        # Uncomment only to determine the correct mining_nonce of above blocks
                        # from qrl.core.PoWValidator import PoWValidator
                        # while not PoWValidator().validate_mining_nonce(state, block_1.blockheader, False):
                        #     block_1.set_nonces(block_1.mining_nonce + 1)
                        #     print(block_1.mining_nonce)
                        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 = 1521889326 + devconfig.minimum_minting_delay * 2
                        block = Block.create(
                            block_number=1,
                            prevblock_headerhash=genesis_block.headerhash,
                            transactions=[],
                            miner_address=bob_xmss.address)
                        block.set_nonces(246, 0)

                        # Uncomment only to determine the correct mining_nonce of above blocks
                        from qrl.core.PoWValidator import PoWValidator
                        while not PoWValidator().validate_mining_nonce(
                                state, block.blockheader, False):
                            block.set_nonces(block.mining_nonce + 1)
                            print(block.mining_nonce)

                    with mock.patch('qrl.core.misc.ntp.getTime') as time_mock:
                        time_mock.return_value = 1521889327 + devconfig.minimum_minting_delay * 3
                        block_2 = Block.create(
                            block_number=2,
                            prevblock_headerhash=block.headerhash,
                            transactions=[],
                            miner_address=bob_xmss.address)
                        block_2.set_nonces(31, 0)

                        # Uncomment only to determine the correct mining_nonce of above blocks
                        # from qrl.core.PoWValidator import PoWValidator
                        # while not PoWValidator().validate_mining_nonce(state, block_2.blockheader, False):
                        #     block_2.set_nonces(block_2.mining_nonce + 1)
                        #     print(block_2.mining_nonce)

                    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_2.block_number)
                    self.assertEqual(chain_manager.last_block.headerhash,
                                     block_2.headerhash)
コード例 #21
0
ファイル: Miner.py プロジェクト: fanff/QRL
class Miner(Qryptominer):
    def __init__(self, pre_block_logic, slaves: list, state: State, add_unprocessed_txn_fn):
        super().__init__()
        self.pre_block_logic = pre_block_logic  # FIXME: Circular dependency with node.py
        self._mining_block = None
        self._slaves = slaves
        self._mining_xmss = None
        self._reward_address = None
        self.state = state
        self._difficulty_tracker = DifficultyTracker()
        self._add_unprocessed_txn_fn = add_unprocessed_txn_fn

    @staticmethod
    def _get_mining_data(block):
        input_bytes = [0x00, 0x00, 0x00, 0x00] + list(block.mining_hash)
        nonce_offset = 0
        return input_bytes, nonce_offset

    @staticmethod
    def calc_hash(input_bytes):
        qn = Qryptonight()
        return qn.hash(input_bytes)

    def set_unused_ots_key(self, xmss, addr_state, start=0):
        for i in range(start, 2 ** xmss.height):
            if not Transaction.ots_key_reuse(addr_state, i):
                xmss.set_index(i)
                return True
        return False

    def valid_mining_permission(self):
        if self._master_address == self._mining_xmss.get_address():
            return True
        addr_state = self.state.get_address(self._master_address)
        access_type = addr_state.get_slave_permission(self._mining_xmss.pk())
        if access_type == -1:
            logger.warning('Slave is not authorized yet for mining')
            logger.warning('Added Slave Txn')
            slave_tx = Transaction.from_json(self._slaves[2])
            self._add_unprocessed_txn_fn(slave_tx, None)
            return None
        return True

    def get_mining_xmss(self):
        if self._mining_xmss:
            addr_state = self.state.get_address(self._mining_xmss.get_address())
            if self.set_unused_ots_key(self._mining_xmss, addr_state, self._mining_xmss.get_index()):
                if self.valid_mining_permission():
                    return self._mining_xmss
            else:
                self._mining_xmss = None
            return None

        if not self._mining_xmss:
            self._master_address = self._slaves[0].encode()
            unused_ots_found = False
            for slave_seed in self._slaves[1]:
                xmss = Wallet.get_new_address(seed=slave_seed).xmss
                addr_state = self.state.get_address(xmss.get_address())
                if self.set_unused_ots_key(xmss, addr_state):  # Unused ots_key_found
                    self._mining_xmss = xmss
                    unused_ots_found = True
                    break

            if not unused_ots_found:  # Unused ots_key_found
                logger.warning('No OTS-KEY left for mining')
                return None

        if self._master_address == self._mining_xmss.get_address():
            return self._mining_xmss

        if not self.valid_mining_permission():
            return None

        return self._mining_xmss

    def start_mining(self,
                     tx_pool,
                     parent_block,
                     parent_difficulty,
                     thread_count=config.user.mining_thread_count):

        mining_xmss = self.get_mining_xmss()
        if not mining_xmss:
            logger.warning('No Mining XMSS Found')
            return

        try:
            self.cancel()
            self._mining_block = self.create_block(last_block=parent_block,
                                                   mining_nonce=0,
                                                   tx_pool=tx_pool,
                                                   signing_xmss=self._mining_xmss,
                                                   master_address=self._master_address)

            measurement = self.state.get_measurement(self._mining_block.timestamp, self._mining_block.prev_headerhash)

            current_difficulty, current_target = self._difficulty_tracker.get(
                measurement=measurement,
                parent_difficulty=parent_difficulty)

            input_bytes, nonce_offset = self._get_mining_data(self._mining_block)
            logger.debug('!!! Mine #{} | {} ({}) | {} -> {} | {}'.format(
                self._mining_block.block_number,
                measurement, self._mining_block.timestamp - parent_block.timestamp,
                UInt256ToString(parent_difficulty), UInt256ToString(current_difficulty),
                current_target
            ))
            logger.debug('!!! {}'.format(current_target))
            self.start(input=input_bytes,
                       nonceOffset=nonce_offset,
                       target=current_target,
                       thread_count=thread_count)
        except Exception as e:
            logger.warning("Exception in start_mining")
            logger.exception(e)

    def solutionEvent(self, nonce):
        # NOTE: This function usually runs in the context of a C++ thread
        try:
            logger.debug('Solution Found %s', nonce)
            self._mining_block.set_mining_nonce(nonce)
            logger.info('Block #%s nonce: %s', self._mining_block.block_number, StringToUInt256(str(nonce))[-4:])
            logger.info('Hash Rate: %s H/s', self.hashRate())
            cloned_block = copy.deepcopy(self._mining_block)
            self.pre_block_logic(cloned_block)
        except Exception as e:
            logger.warning("Exception in solutionEvent")
            logger.exception(e)

    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
コード例 #22
0
    def test_verify(self):

        class CustomQMiner(Qryptominer):
            def __init__(self):
                Qryptominer.__init__(self)
                self._solution_lock = threading.Lock()
                self.nonce = None
                self.solution_blob = None

            def start(self, input, nonceOffset, target, thread_count):
                self.cancel()
                try:
                    self._solution_lock.release()
                except RuntimeError:
                    pass
                self._solution_lock.acquire(blocking=False)
                super().start(input, nonceOffset, target, thread_count)

            def wait_for_solution(self):
                self._solution_lock.acquire(blocking=True)
                self._solution_lock.release()

            def handleEvent(self, event):
                if event.type == SOLUTION:
                    self.nonce = event.nonce
                    self.solution_blob = self.solutionInput()
                    self._solution_lock.release()

        block_timestamp = 1515443508
        parent_block_timestamp = 1515443508

        # This could be the average of last N blocks
        measurement = block_timestamp - parent_block_timestamp

        parent_difficulty = (0, 0, 0, 0, 0, 0, 0, 0,
                             0, 0, 0, 0, 0, 0, 0, 0,
                             0, 0, 0, 0, 0, 0, 0, 0,
                             0, 0, 0, 0, 0, 0, 0, 4)

        new_diff, new_target = DifficultyTracker.get(
            measurement,
            parent_difficulty=parent_difficulty)

        self.assertEqual(new_diff, (0, 0, 0, 0, 0, 0, 0, 0,
                                    0, 0, 0, 0, 0, 0, 0, 0,
                                    0, 0, 0, 0, 0, 0, 0, 0,
                                    0, 0, 0, 0, 0, 0, 0, 5))

        self.assertEqual(new_target, (
            51, 51, 51, 51, 51, 51, 51, 51,
            51, 51, 51, 51, 51, 51, 51, 51,
            51, 51, 51, 51, 51, 51, 51, 51,
            51, 51, 51, 51, 51, 51, 51, 51))

        block_json = read_data_file('core/example_block_mining.json')

        block = Block.from_json(block_json)

        expected_blob = (0, 231, 90, 101, 142, 20, 245, 183, 96, 5, 216, 159, 111, 239, 93, 217, 138, 10, 227, 159, 198,
                         207, 109, 238, 83, 220, 167, 148, 247, 200, 197, 41, 37, 36, 150, 12, 116, 85, 254, 0, 0, 0, 0,
                         0, 0, 0, 0, 0, 0, 0, 0, 181, 198, 40, 62, 106, 139, 108, 83, 216, 206, 161, 148, 50, 65, 212,
                         137, 94, 102, 124, 45, 51, 57, 43, 19, 51)
        self.assertEqual(expected_blob, tuple(block.mining_blob))

        custom_qminer = CustomQMiner()
        custom_qminer.start(input=block.mining_blob,
                            nonceOffset=block.mining_nonce_offset,
                            target=new_target,
                            thread_count=2)
        custom_qminer.wait_for_solution()

        expected_mined_blob = bytearray(expected_blob)
        tmp_offset = config.dev.mining_nonce_offset
        expected_mined_blob[tmp_offset:tmp_offset + 4] = custom_qminer.nonce.to_bytes(4,
                                                                                      byteorder='big',
                                                                                      signed=False)

        print(custom_qminer.nonce)
        self.assertEqual(tuple(expected_mined_blob), custom_qminer.solution_blob)
        self.assertTrue(PoWHelper().verifyInput(custom_qminer.solution_blob, new_target))
コード例 #23
0
ファイル: test_ChainManager.py プロジェクト: nerdy-dad/QRL
    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_target(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 = 1519601174  # Very high to get an easy difficulty
                        block_1 = Block.create(
                            block_number=1,
                            prevblock_headerhash=genesis_block.headerhash,
                            transactions=[],
                            signing_xmss=alice_xmss,
                            master_address=alice_xmss.address,
                            nonce=1)
                        block_1.set_mining_nonce(10)

                        while not PoWValidator().validate_mining_nonce(
                                state, block_1.blockheader, 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 = 1519601174 + devconfig.minimum_minting_delay * 2
                        block = Block.create(
                            block_number=1,
                            prevblock_headerhash=genesis_block.headerhash,
                            transactions=[],
                            signing_xmss=bob_xmss,
                            master_address=bob_xmss.address,
                            nonce=1)
                        block.set_mining_nonce(18)

                        while not PoWValidator().validate_mining_nonce(
                                state, block.blockheader, False):
                            block.set_mining_nonce(block.mining_nonce + 1)

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

                    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_2.block_number)
                    self.assertEqual(chain_manager.last_block.headerhash,
                                     block_2.headerhash)
コード例 #24
0
ファイル: test_ChainManager.py プロジェクト: nerdy-dad/QRL
    def test_multi_output_transaction_add_block(self):
        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()
                random_xmss = get_random_xmss()
                transfer_transaction = TransferTransaction.create(
                    addr_from=bob_xmss.address,
                    addrs_to=[alice_xmss.address, random_xmss.address],
                    amounts=[
                        40 * int(config.dev.shor_per_quanta),
                        59 * int(config.dev.shor_per_quanta)
                    ],
                    fee=1 * config.dev.shor_per_quanta,
                    xmss_pk=bob_xmss.pk)
                transfer_transaction._data.nonce = 1
                transfer_transaction.sign(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_target(tmp_difficulty)
                chain_manager._difficulty_tracker.get = MagicMock(
                    return_value=(tmp_difficulty, tmp_boundary))

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

                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(
                        block_number=1,
                        prevblock_headerhash=genesis_block.headerhash,
                        transactions=[transfer_transaction],
                        signing_xmss=alice_xmss,
                        master_address=alice_xmss.address,
                        nonce=1)

                    while not PoWValidator().validate_mining_nonce(
                            state, block_1.blockheader, 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_addr_state = state.get_address(bob_xmss.address)
                alice_addr_state = state.get_address(alice_xmss.address)
                random_addr_state = state.get_address(random_xmss.address)

                self.assertEqual(bob_addr_state.balance, 0)
                self.assertEqual(
                    alice_addr_state.balance,
                    140 * int(config.dev.shor_per_quanta) +
                    block_1.block_reward + block_1.fee_reward)
                self.assertEqual(random_addr_state.balance,
                                 159 * int(config.dev.shor_per_quanta))
コード例 #25
0
    def test_add_4(self, mock_difficulty_tracker_get):
        with set_qrl_dir('wallet_ver1'):
            with State() as state:
                with mocked_genesis() as custom_genesis:
                    chain_manager = ChainManager(state)

                    chain_manager._difficulty_tracker = Mock()
                    tmp_difficulty = StringToUInt256('2')
                    tmp_target = DifficultyTracker.get_target(tmp_difficulty)
                    mock_difficulty_tracker_get.return_value = [
                        tmp_difficulty, tmp_target
                    ]

                    alice_xmss = get_alice_xmss()
                    slave_xmss = XMSS(
                        XmssFast(alice_xmss.seed, alice_xmss.height))
                    random_xmss1 = get_random_xmss()
                    random_kyber1 = Kyber()
                    random_dilithium1 = Dilithium()
                    random_xmss2 = get_random_xmss()
                    random_kyber2 = Kyber()
                    random_dilithium2 = Dilithium()

                    message = b'Hello World How are you?'
                    prf512_seed = b'10192'

                    custom_genesis.genesis_balance.extend([
                        qrl_pb2.GenesisBalance(address=random_xmss1.address,
                                               balance=65000000000000000)
                    ])
                    custom_genesis.genesis_balance.extend([
                        qrl_pb2.GenesisBalance(address=random_xmss2.address,
                                               balance=65000000000000000)
                    ])
                    chain_manager.load(custom_genesis)

                    with mock.patch('qrl.core.misc.ntp.getTime') as time_mock:
                        time_mock.return_value = 1615270948

                        lattice_public_key_txn = LatticePublicKey.create(
                            fee=1,
                            kyber_pk=random_kyber1.getPK(),
                            dilithium_pk=random_dilithium1.getPK(),
                            xmss_pk=random_xmss1.pk)
                        lattice_public_key_txn._data.nonce = 1
                        lattice_public_key_txn.sign(random_xmss1)
                        genesis_block = GenesisBlock()
                        tmp_block1 = Block.create(
                            block_number=1,
                            prev_block_headerhash=genesis_block.headerhash,
                            prev_block_timestamp=genesis_block.timestamp,
                            transactions=[lattice_public_key_txn],
                            miner_address=slave_xmss.address)

                        #  Mine the nonce
                        while not PoWValidator().validate_mining_nonce(
                                state, tmp_block1.blockheader, False):
                            tmp_block1.set_nonces(tmp_block1.mining_nonce + 1,
                                                  0)

                        res = chain_manager.add_block(block=tmp_block1)
                        self.assertTrue(res)

                        # Need to move forward the time to align with block times
                        time_mock.return_value += config.dev.minimum_minting_delay * 2

                        encrypted_eph_message = create_ephemeral_channel(
                            msg_id=lattice_public_key_txn.txhash,
                            ttl=time_mock.return_value,
                            ttr=0,
                            addr_from=random_xmss2.address,
                            kyber_pk=random_kyber2.getPK(),
                            kyber_sk=random_kyber2.getSK(),
                            receiver_kyber_pk=random_kyber1.getPK(),
                            dilithium_pk=random_dilithium2.getPK(),
                            dilithium_sk=random_dilithium2.getSK(),
                            prf512_seed=prf512_seed,
                            data=message,
                            nonce=1)

                        chain_manager.state.update_ephemeral(
                            encrypted_eph_message)
                        eph_metadata = chain_manager.state.get_ephemeral_metadata(
                            lattice_public_key_txn.txhash)

                        # Decrypting Payload

                        encrypted_eph_message = eph_metadata.encrypted_ephemeral_message_list[
                            0]
                        encrypted_payload = encrypted_eph_message.payload

                        random_kyber1.kem_decode(
                            encrypted_eph_message.channel.enc_aes256_symkey)
                        aes_key = bytes(random_kyber1.getMyKey())
                        myAES = AES(aes_key)
                        decrypted_payload = myAES.decrypt(encrypted_payload)
                        ephemeral_channel_payload = EphemeralChannelPayload.from_json(
                            decrypted_payload)

                        self.assertEqual(ephemeral_channel_payload.prf512_seed,
                                         b'10192')
                        self.assertEqual(ephemeral_channel_payload.data,
                                         b'Hello World How are you?')

                        # TODO (cyyber): Add Ephemeral Testing code using Naive RNG

                        tmp_block2 = Block.create(
                            block_number=2,
                            prev_block_headerhash=tmp_block1.headerhash,
                            prev_block_timestamp=tmp_block1.timestamp,
                            transactions=[],
                            miner_address=slave_xmss.address)

                        #  Mine the nonce
                        while not PoWValidator().validate_mining_nonce(
                                state, tmp_block2.blockheader, False):
                            tmp_block2.set_nonces(tmp_block2.mining_nonce + 1,
                                                  0)

                        res = chain_manager.add_block(block=tmp_block2)
                        self.assertTrue(res)

                        # Need to move forward the time to align with block times
                        time_mock.return_value += config.dev.minimum_minting_delay * 2

                        tmp_block3 = Block.create(
                            block_number=3,
                            prev_block_headerhash=tmp_block2.headerhash,
                            prev_block_timestamp=tmp_block1.timestamp,
                            transactions=[],
                            miner_address=slave_xmss.address)

                        #  Mine the nonce
                        while not PoWValidator().validate_mining_nonce(
                                state, tmp_block3.blockheader, False):
                            tmp_block3.set_nonces(tmp_block3.mining_nonce + 1,
                                                  0)

                        res = chain_manager.add_block(block=tmp_block3)
                        self.assertTrue(res)

                        time_mock.return_value += config.dev.minimum_minting_delay

                        tmp_block4 = Block.create(
                            block_number=4,
                            prev_block_headerhash=tmp_block3.headerhash,
                            prev_block_timestamp=tmp_block1.timestamp,
                            transactions=[],
                            miner_address=slave_xmss.address)

                        #  Mine the nonce
                        while not PoWValidator().validate_mining_nonce(
                                state, tmp_block4.blockheader, False):
                            tmp_block4.set_nonces(tmp_block4.mining_nonce + 1,
                                                  0)

                        res = chain_manager.add_block(block=tmp_block4)
                        self.assertTrue(res)

                        address_state = chain_manager.get_address(
                            random_xmss1.address)

                        self.assertEqual(
                            address_state.latticePK_list[0].kyber_pk,
                            lattice_public_key_txn.kyber_pk)
                        self.assertEqual(
                            address_state.latticePK_list[0].dilithium_pk,
                            lattice_public_key_txn.dilithium_pk)

                        self.assertEqual(address_state.address,
                                         lattice_public_key_txn.addr_from)

                        random_xmss1_state = chain_manager.get_address(
                            random_xmss1.address)

                        self.assertEqual(64999999999999999,
                                         random_xmss1_state.balance)
コード例 #26
0
def ask_difficulty_tracker(difficulty: str):
    dt = DifficultyTracker()
    tmp_difficulty = StringToUInt256('2')
    tmp_target = dt.get_target(tmp_difficulty)
    return tmp_difficulty, tmp_target
コード例 #27
0
ファイル: ChainManager.py プロジェクト: scottdonaldau/QRL
    def load(self, genesis_block):
        # load() has the following tasks:
        # Write Genesis Block into State immediately
        # Register block_number <-> blockhash mapping
        # Calculate difficulty Metadata for Genesis Block
        # Generate AddressStates from Genesis Block balances
        # Apply Genesis Block's transactions to the state
        # Detect if we are forked from genesis block and if so initiate recovery.
        height = self._state.get_mainchain_height()

        if height == -1:
            self._state.put_block(genesis_block, None)
            block_number_mapping = qrl_pb2.BlockNumberMapping(
                headerhash=genesis_block.headerhash,
                prev_headerhash=genesis_block.prev_headerhash)

            self._state.put_block_number_mapping(genesis_block.block_number,
                                                 block_number_mapping, None)
            parent_difficulty = StringToUInt256(
                str(config.user.genesis_difficulty))

            self.current_difficulty, _ = DifficultyTracker.get(
                measurement=config.dev.mining_setpoint_blocktime,
                parent_difficulty=parent_difficulty)

            block_metadata = BlockMetadata.create()
            block_metadata.set_block_difficulty(self.current_difficulty)
            block_metadata.set_cumulative_difficulty(self.current_difficulty)

            self._state.put_block_metadata(genesis_block.headerhash,
                                           block_metadata, None)
            addresses_state = dict()
            for genesis_balance in GenesisBlock().genesis_balance:
                bytes_addr = genesis_balance.address
                addresses_state[bytes_addr] = AddressState.get_default(
                    bytes_addr)
                addresses_state[
                    bytes_addr]._data.balance = genesis_balance.balance

            for tx_idx in range(1, len(genesis_block.transactions)):
                tx = Transaction.from_pbdata(
                    genesis_block.transactions[tx_idx])
                for addr in tx.addrs_to:
                    addresses_state[addr] = AddressState.get_default(addr)

            coinbase_tx = Transaction.from_pbdata(
                genesis_block.transactions[0])

            if not isinstance(coinbase_tx, CoinBase):
                return False

            addresses_state[coinbase_tx.addr_to] = AddressState.get_default(
                coinbase_tx.addr_to)

            if not coinbase_tx.validate_extended(genesis_block.block_number):
                return False

            coinbase_tx.apply_state_changes(addresses_state)

            for tx_idx in range(1, len(genesis_block.transactions)):
                tx = Transaction.from_pbdata(
                    genesis_block.transactions[tx_idx])
                tx.apply_state_changes(addresses_state)

            self._state.put_addresses_state(addresses_state)
            self._state.update_tx_metadata(genesis_block, None)
            self._state.update_mainchain_height(0, None)
        else:
            self._last_block = self.get_block_by_number(height)
            self.current_difficulty = self._state.get_block_metadata(
                self._last_block.headerhash).block_difficulty
            fork_state = self._state.get_fork_state()
            if fork_state:
                block = self._state.get_block(fork_state.initiator_headerhash)
                self._fork_recovery(block, fork_state)
コード例 #28
0
ファイル: test_ChainManager.py プロジェクト: fanff/QRL
    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)
コード例 #29
0
    def test_verify(self):
        class CustomQMiner(Qryptominer):
            def __init__(self):
                Qryptominer.__init__(self)
                self._solution_lock = threading.Lock()
                self.nonce = None
                self.solution_blob = None

            def start(self, input, nonceOffset, target, thread_count):
                self.cancel()
                try:
                    self._solution_lock.release()
                except RuntimeError:
                    pass
                self._solution_lock.acquire(blocking=False)
                super().start(input, nonceOffset, target, thread_count)

            def wait_for_solution(self):
                self._solution_lock.acquire(blocking=True)
                self._solution_lock.release()

            def solutionEvent(self, nonce):
                print('Solution Found %s', nonce)
                self.nonce = nonce
                self.solution_blob = self.solutionInput()
                self._solution_lock.release()

        block_timestamp = 1515443508
        parent_block_timestamp = 1515443508

        # This could be the average of last N blocks
        measurement = block_timestamp - parent_block_timestamp

        parent_difficulty = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4)

        new_diff, new_target = DifficultyTracker.get(
            measurement, parent_difficulty=parent_difficulty)

        self.assertEqual(new_diff,
                         (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5))

        self.assertEqual(
            new_target,
            (51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
             51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51))

        block_json = read_data_file('core/example_block_mining.json')

        block = Block.from_json(block_json)

        expected_blob = tuple([
            241, 93, 178, 239, 171, 183, 27, 87, 2, 191, 178, 157, 32, 74, 254,
            207, 242, 82, 128, 197, 58, 86, 24, 90, 106, 33, 58, 82, 160, 251,
            118, 174, 45, 182, 72, 157, 142, 141, 219, 0, 0, 0, 15, 61, 11, 20,
            166, 132, 14, 29, 248, 65, 55, 56, 226, 12, 57, 60, 37, 64, 123,
            44, 48, 172, 218, 221, 26, 8, 143, 110, 38, 215, 83, 248, 227, 87,
            148, 88, 237, 48, 203, 111, 245, 31, 125, 45, 14, 111, 109, 0, 87,
            13, 154, 252, 49, 160
        ])

        self.assertEqual(expected_blob, tuple(block.mining_blob))

        custom_qminer = CustomQMiner()
        custom_qminer.start(input=block.mining_blob,
                            nonceOffset=block.mining_nonce_offset,
                            target=new_target,
                            thread_count=2)
        custom_qminer.wait_for_solution()

        expected_mined_blob = bytearray(expected_blob)
        tmp_offset = config.dev.mining_nonce_offset
        expected_mined_blob[tmp_offset:tmp_offset +
                            4] = custom_qminer.nonce.to_bytes(4,
                                                              byteorder='big',
                                                              signed=False)

        print(custom_qminer.nonce)
        self.assertEqual(tuple(expected_mined_blob),
                         custom_qminer.solution_blob)
        self.assertTrue(PoWHelper().verifyInput(custom_qminer.solution_blob,
                                                new_target))