コード例 #1
0
    def rollback_tx_metadata(state: State, block, batch):
        fee_reward = 0
        for protobuf_txn in block.transactions:
            txn = Transaction.from_pbdata(protobuf_txn)
            fee_reward += txn.fee
            TransactionMetadata.remove_tx_metadata(state, txn, batch)

        txn = Transaction.from_pbdata(
            block.transactions[0])  # Coinbase Transaction
        state._update_total_coin_supply(fee_reward - txn.amount, batch)
        LastTransactions._remove_last_tx(state, block, batch)
コード例 #2
0
ファイル: PublicAPIService.py プロジェクト: jack3343/xrd-core
    def PushTransaction(self, request: xrd_pb2.PushTransactionReq,
                        context) -> xrd_pb2.PushTransactionResp:
        logger.debug("[PublicAPI] PushTransaction")
        answer = xrd_pb2.PushTransactionResp()

        try:
            tx = Transaction.from_pbdata(request.transaction_signed)
            tx.update_txhash()

            # FIXME: Full validation takes too much time. At least verify there is a signature
            # the validation happens later in the tx pool
            if len(tx.signature) > 1000:
                self.xrdnode.submit_send_tx(tx)
                answer.error_code = xrd_pb2.PushTransactionResp.SUBMITTED
                answer.tx_hash = tx.txhash
            else:
                answer.error_description = 'Signature too short'
                answer.error_code = xrd_pb2.PushTransactionResp.VALIDATION_FAILED

        except Exception as e:
            error_str = traceback.format_exception(None, e, e.__traceback__)
            answer.error_description = str(''.join(error_str))
            answer.error_code = xrd_pb2.PushTransactionResp.ERROR

        return answer
コード例 #3
0
    def update_tx_metadata(state: State, block, batch) -> bool:
        fee_reward = 0

        for protobuf_txn in block.transactions:
            txn = Transaction.from_pbdata(protobuf_txn)
            fee_reward += txn.fee
            if not TransactionMetadata.put_tx_metadata(
                    state, txn, block.block_number, block.timestamp, batch):
                return False

        txn = Transaction.from_pbdata(
            block.transactions[0])  # Coinbase Transaction
        state._update_total_coin_supply(txn.amount - fee_reward, batch)
        LastTransactions._update_last_tx(state, block, batch)

        return True
コード例 #4
0
def tx_push(ctx, txblob):
    """
    Sends a signed transaction blob to a node
    """
    tx = None
    try:
        txbin = parse_hexblob(txblob)
        pbdata = xrd_pb2.Transaction()
        pbdata.ParseFromString(txbin)
        tx = Transaction.from_pbdata(pbdata)
    except Exception as e:
        click.echo("tx blob is not valid")
        quit(1)

    tmp_json = tx.to_json()
    # FIXME: binary fields are represented in base64. Improve output
    print(tmp_json)
    if len(tx.signature) == 0:
        click.echo('Signature missing')
        quit(1)

    stub = ctx.obj.get_stub_public_api()
    pushTransactionReq = xrd_pb2.PushTransactionReq(transaction_signed=tx.pbdata)
    pushTransactionResp = stub.PushTransaction(pushTransactionReq, timeout=CONNECTION_TIMEOUT)
    print(pushTransactionResp.error_code)
コード例 #5
0
 def get_tx_metadata(state: State, txhash: bytes):
     try:
         tx_metadata = TransactionMetadata.deserialize(
             state._db.get_raw(txhash))
         data, block_number = tx_metadata.transaction, tx_metadata.block_number
         return Transaction.from_pbdata(data), block_number
     except Exception:
         return None
コード例 #6
0
ファイル: TransactionPool.py プロジェクト: jack3343/xrd-core
 def add_tx_from_block_to_pool(self, block: Block, current_block_number):
     """
     Move all transactions from block to transaction pool.
     :param block:
     :return:
     """
     for protobuf_tx in block.transactions[1:]:
         if not self.add_tx_to_pool(Transaction.from_pbdata(protobuf_tx), current_block_number):
             logger.warning('Failed to Add transaction into transaction pool')
             logger.warning('Block #%s %s', block.block_number, bin2hstr(block.headerhash))
             return
コード例 #7
0
 def test_update_mining_address(self):
     self.block.update_mining_address(dev_config=config.dev,
                                      mining_address=bob.address)
     coinbase_tx = Transaction.from_pbdata(self.block.transactions[0])
     self.assertTrue(isinstance(coinbase_tx, CoinBase))
     self.assertEqual(coinbase_tx.addr_to, bob.address)
     hashedtransactions = []
     for tx in self.block.transactions:
         hashedtransactions.append(tx.transaction_hash)
     self.assertEqual(self.block.blockheader.tx_merkle_root,
                      merkle_tx_hash(hashedtransactions))
コード例 #8
0
    def update_mining_address(self, dev_config: DevConfig,
                              mining_address: bytes):
        coinbase_tx = Transaction.from_pbdata(self.transactions[0])
        coinbase_tx.update_mining_address(mining_address)
        hashedtransactions = []

        for tx in self.transactions:
            hashedtransactions.append(tx.transaction_hash)

        self.blockheader.update_merkle_root(dev_config,
                                            merkle_tx_hash(hashedtransactions))

        self._data.header.MergeFrom(self.blockheader.pbdata)
コード例 #9
0
ファイル: helper.py プロジェクト: jack3343/xrd-core
def get_genesis_with_only_coin_base_txn(coin_base_reward_addr, dev_config):
    g = GenesisBlock()

    coin_base_tx = Transaction.from_pbdata(g.transactions[0])
    coin_base_tx.update_mining_address(coin_base_reward_addr)

    # Remove all other transaction except CoinBase txn
    del g.transactions[:]

    g.pbdata.transactions.extend([coin_base_tx.pbdata])
    g.blockheader.generate_headerhash(dev_config)

    return g
コード例 #10
0
ファイル: LastTransactions.py プロジェクト: jack3343/xrd-core
    def _remove_last_tx(state: State, block: Block, batch):
        if len(block.transactions) == 0:
            return

        try:
            last_txn = LastTransactions.deserialize(
                state._db.get_raw(b'last_txn'))
        except KeyError:
            return

        for protobuf_txn in block.transactions:
            txn = Transaction.from_pbdata(protobuf_txn)
            i = 0
            while i < len(last_txn.tx_metadata):
                tx = Transaction.from_pbdata(
                    last_txn.tx_metadata[i].transaction)
                if txn.txhash == tx.txhash:
                    del last_txn.tx_metadata[i]
                    break
                i += 1

        state._db.put_raw(b'last_txn', last_txn.serialize(), batch)
コード例 #11
0
ファイル: LastTransactions.py プロジェクト: jack3343/xrd-core
    def get_last_txs(state: State):
        try:
            last_txn = LastTransactions.deserialize(
                state._db.get_raw(b'last_txn'))
        except KeyError:
            return []
        except Exception as e:  # noqa
            logger.warning("[get_last_txs] Exception during call %s", e)
            return []

        txs = []
        for tx_metadata in last_txn.tx_metadata:
            data = tx_metadata.transaction
            tx = Transaction.from_pbdata(data)
            txs.append(tx)

        return txs
コード例 #12
0
def tx_inspect(ctx, txblob):
    """
    Inspected a transaction blob
    """
    tx = None
    try:
        txbin = parse_hexblob(txblob)
        pbdata = xrd_pb2.Transaction()
        pbdata.ParseFromString(txbin)
        tx = Transaction.from_pbdata(pbdata)
    except Exception as e:
        click.echo("tx blob is not valid")
        quit(1)

    tmp_json = tx.to_json()
    # FIXME: binary fields are represented in base64. Improve output
    print(tmp_json)
コード例 #13
0
ファイル: LastTransactions.py プロジェクト: jack3343/xrd-core
    def _update_last_tx(state: State, block: Block, batch):
        if len(block.transactions) == 0:
            return
        last_txn = LastTransactions()

        try:
            last_txn = LastTransactions.deserialize(
                state._db.get_raw(b'last_txn'))
        except KeyError:
            pass

        for protobuf_txn in block.transactions[-20:]:
            txn = Transaction.from_pbdata(protobuf_txn)
            if isinstance(txn, CoinBase):
                continue
            last_txn.add(txn, block.block_number, block.timestamp)

        state._db.put_raw(b'last_txn', last_txn.serialize(), batch)
コード例 #14
0
ファイル: TransactionPool.py プロジェクト: jack3343/xrd-core
    def remove_tx_in_block_from_pool(self, block_obj: Block):
        for protobuf_tx in block_obj.transactions[1:]:  # Ignore first transaction, as it is a coinbase txn
            tx = Transaction.from_pbdata(protobuf_tx)
            if tx.ots_key < config.dev.max_ots_tracking_index:
                idx = self.get_tx_index_from_pool(tx.txhash)
                if idx > -1:
                    del self.transaction_pool[idx]
            else:
                i = 0
                while i < len(self.transaction_pool):
                    txn = self.transaction_pool[i][1].transaction
                    if txn.PK == tx.PK:
                        if txn.ots_key >= config.dev.max_ots_tracking_index:
                            if txn.ots_key <= tx.ots_key:
                                del self.transaction_pool[i]
                                continue
                    i += 1

        heapq.heapify(self.transaction_pool)
コード例 #15
0
ファイル: p2pTxManagement.py プロジェクト: jack3343/xrd-core
    def handle_token_transaction(source, message: xrdlegacy_pb2.LegacyMessage):
        """
        Token Transaction
        This function processes whenever a Transaction having
        subtype TOKEN is received.
        :return:
        """
        P2PBaseObserver._validate_message(message,
                                          xrdlegacy_pb2.LegacyMessage.TK)
        try:
            tx = Transaction.from_pbdata(message.tkData)
        except Exception as e:
            logger.error(
                'Token Txn rejected - unable to decode serialised data - closing connection'
            )
            logger.exception(e)
            source.loseConnection()
            return

        if source.factory.master_mr.isRequested(tx.get_message_hash(), source):
            source.factory.add_unprocessed_txn(tx, source.peer.ip)
コード例 #16
0
ファイル: p2pTxManagement.py プロジェクト: jack3343/xrd-core
    def handle_tx(source, message: xrdlegacy_pb2.LegacyMessage):
        """
        Transaction
        Executed whenever a new TX type message is received.
        :return:
        """
        P2PBaseObserver._validate_message(message,
                                          xrdlegacy_pb2.LegacyMessage.TX)
        try:
            tx = Transaction.from_pbdata(message.txData)
        except Exception as e:
            logger.error(
                'Message Txn rejected - unable to decode serialised data - closing connection'
            )
            logger.exception(e)
            source.loseConnection()
            return

        # NOTE: Connects to MR
        if source.factory.master_mr.isRequested(tx.get_message_hash(), source):
            source.factory.add_unprocessed_txn(tx, source.peer.ip)
コード例 #17
0
ファイル: p2pTxManagement.py プロジェクト: jack3343/xrd-core
    def handle_lattice(source, message: xrdlegacy_pb2.LegacyMessage):
        """
        Receives Lattice Public Key Transaction
        :param source:
        :param message:
        :return:
        """
        P2PBaseObserver._validate_message(message,
                                          xrdlegacy_pb2.LegacyMessage.LT)
        try:
            tx = Transaction.from_pbdata(message.ltData)
        except Exception as e:
            logger.error(
                'lattice_public_key rejected - unable to decode serialised data - closing connection'
            )
            logger.exception(e)
            source.loseConnection()
            return

        if source.factory.master_mr.isRequested(tx.get_message_hash(), source):
            source.factory.add_unprocessed_txn(tx, source.peer.ip)
コード例 #18
0
ファイル: p2pTxManagement.py プロジェクト: jack3343/xrd-core
    def handle_multi_sig_vote(source, message: xrdlegacy_pb2.LegacyMessage):
        """
        Handles Multi Sig Transaction
        :param source:
        :param message:
        :return:
        """
        P2PBaseObserver._validate_message(message,
                                          xrdlegacy_pb2.LegacyMessage.MV)
        try:
            tx = Transaction.from_pbdata(message.mvData)
        except Exception as e:
            logger.error(
                'multi_sig_vote txn rejected - unable to decode serialised data - closing connection'
            )
            logger.exception(e)
            source.loseConnection()
            return

        if source.factory.master_mr.isRequested(tx.get_message_hash(), source):
            source.factory.add_unprocessed_txn(tx, source.peer.ip)
コード例 #19
0
    def validate(self, chain_manager, future_blocks: OrderedDict) -> bool:
        if chain_manager.get_block_is_duplicate(self):
            logger.warning('Duplicate Block #%s %s', self.block_number,
                           bin2hstr(self.headerhash))
            return False

        parent_block = chain_manager.get_block(self.prev_headerhash)
        dev_config = chain_manager.get_config_by_block_number(
            self.block_number)

        # If parent block not found in state, then check if its in the future block list
        if not parent_block:
            try:
                parent_block = future_blocks[self.prev_headerhash]
            except KeyError:
                logger.warning('Parent block not found')
                logger.warning('Parent block headerhash %s',
                               bin2hstr(self.prev_headerhash))
                return False

        if not self._validate_parent_child_relation(parent_block):
            logger.warning('Failed to validate blocks parent child relation')
            return False

        if not chain_manager.validate_mining_nonce(self.blockheader,
                                                   dev_config):
            logger.warning('Failed PoW Validation')
            return False

        if len(self.transactions) == 0:
            return False

        try:
            state_container = chain_manager.new_state_container(
                set(), self.block_number, False, None)

            coinbase_txn = Transaction.from_pbdata(self.transactions[0])
            coinbase_amount = coinbase_txn.amount

            if not coinbase_txn.validate_all(state_container):
                return False

        except Exception as e:
            logger.warning('Exception %s', e)
            return False

        # Build transaction merkle tree, calculate fee reward, and then see if BlockHeader also agrees.
        hashedtransactions = []

        for tx in self.transactions:
            tx = Transaction.from_pbdata(tx)
            hashedtransactions.append(tx.txhash)

        fee_reward = 0
        for index in range(1, len(self.transactions)):
            fee_reward += self.transactions[index].fee

        qn = Qryptonight()
        seed_block = chain_manager.get_block_by_number(
            qn.get_seed_height(self.block_number))

        self.blockheader._seed_height = seed_block.block_number
        self.blockheader._seed_hash = seed_block.headerhash

        if not self.blockheader.validate(fee_reward, coinbase_amount,
                                         merkle_tx_hash(hashedtransactions),
                                         dev_config):
            return False

        return True
コード例 #20
0
ファイル: helper.py プロジェクト: jack3343/xrd-core
def gen_blocks(block_count, state, miner_address):
    blocks = []
    block = None
    with mock.patch('xrd.core.misc.ntp.getTime') as time_mock:
        time_mock.return_value = 1615270948
        addresses_state = dict()
        for i in range(0, block_count):
            if i == 0:
                block = GenesisBlock()
                for genesis_balance in GenesisBlock().genesis_balance:
                    bytes_addr = genesis_balance.address
                    addresses_state[
                        bytes_addr] = OptimizedAddressState.get_default(
                            bytes_addr)
                    addresses_state[
                        bytes_addr]._data.balance = genesis_balance.balance
            else:
                block = Block.create(dev_config=config.dev,
                                     block_number=i,
                                     prev_headerhash=block.headerhash,
                                     prev_timestamp=block.timestamp,
                                     transactions=[],
                                     miner_address=miner_address,
                                     seed_height=None,
                                     seed_hash=None)
                addresses_set = ChainManager.set_affected_address(block)
                coin_base_tx = Transaction.from_pbdata(block.transactions[0])
                coin_base_tx.set_affected_address(addresses_set)

                chain_manager = ChainManager(state)
                state_container = chain_manager.new_state_container(
                    addresses_set, block.block_number, False, None)
                coin_base_tx.apply(state, state_container)

                for tx_idx in range(1, len(block.transactions)):
                    tx = Transaction.from_pbdata(block.transactions[tx_idx])
                    if not chain_manager.update_state_container(
                            tx, state_container):
                        return False
                    tx.apply(state, state_container)

                block.set_nonces(dev_config=config.dev,
                                 mining_nonce=10,
                                 extra_nonce=0)
            blocks.append(block)

            metadata = BlockMetadata()
            metadata.set_block_difficulty(StringToUInt256('256'))
            BlockMetadata.put_block_metadata(state, block.headerhash, metadata,
                                             None)

            Block.put_block(state, block, None)
            bm = xrd_pb2.BlockNumberMapping(
                headerhash=block.headerhash,
                prev_headerhash=block.prev_headerhash)

            Block.put_block_number_mapping(state, block.block_number, bm, None)
            state.update_mainchain_height(block.block_number, None)
            OptimizedAddressState.put_optimized_addresses_state(
                state, addresses_state)

    return blocks
コード例 #21
0
ファイル: PublicAPIService.py プロジェクト: jack3343/xrd-core
    def GetObject(self, request: xrd_pb2.GetObjectReq,
                  context) -> xrd_pb2.GetObjectResp:
        logger.debug("[PublicAPI] GetObject")
        answer = xrd_pb2.GetObjectResp()
        answer.found = False

        # FIXME: We need a unified way to access and validate data.
        query = bytes(
            request.query
        )  # query will be as a string, if Q is detected convert, etc.

        try:
            if AddressState.address_is_valid(query):
                if self.xrdnode.get_address_is_used(query):
                    address_state = self.xrdnode.get_optimized_address_state(
                        query)
                    if address_state is not None:
                        answer.found = True
                        answer.address_state.CopyFrom(address_state.pbdata)
                        return answer
        except ValueError:
            pass

        transaction_block_number = self.xrdnode.get_transaction(query)
        transaction = None
        blockheader = None
        if transaction_block_number:
            transaction, block_number = transaction_block_number
            answer.found = True
            block = self.xrdnode.get_block_from_index(block_number)
            blockheader = block.blockheader.pbdata
            timestamp = block.blockheader.timestamp
        else:
            transaction_timestamp = self.xrdnode.get_unconfirmed_transaction(
                query)
            if transaction_timestamp:
                transaction, timestamp = transaction_timestamp
                answer.found = True

        if transaction:
            txextended = xrd_pb2.TransactionExtended(
                header=blockheader,
                tx=transaction.pbdata,
                addr_from=transaction.addr_from,
                size=transaction.size,
                timestamp_seconds=timestamp)
            answer.transaction.CopyFrom(txextended)
            return answer

        # NOTE: This is temporary, indexes are accepted for blocks
        try:
            block = self.xrdnode.get_block_from_hash(query)
            if block is None or (block.block_number == 0
                                 and block.prev_headerhash !=
                                 config.user.genesis_prev_headerhash):
                query_str = query.decode()
                query_index = int(query_str)
                block = self.xrdnode.get_block_from_index(query_index)
                if not block:
                    return answer

            answer.found = True
            block_extended = xrd_pb2.BlockExtended()
            block_extended.header.CopyFrom(block.blockheader.pbdata)
            block_extended.size = block.size
            for transaction in block.transactions:
                tx = Transaction.from_pbdata(transaction)
                extended_tx = xrd_pb2.TransactionExtended(
                    tx=transaction,
                    addr_from=tx.addr_from,
                    size=tx.size,
                    timestamp_seconds=block.blockheader.timestamp)
                block_extended.extended_transactions.extend([extended_tx])
            answer.block_extended.CopyFrom(block_extended)
            return answer
        except Exception:
            pass

        return answer
コード例 #22
0
    def test_messageTxn_sign(self):
        with set_xrd_dir('wallet_ver1'):
            with State() as db_state:
                p2p_factory = Mock(spec=P2PFactory)
                p2p_factory.pow = Mock(spec=POW)
                chain_manager = ChainManager(db_state)

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

                service = PublicAPIService(xrdnode)

                context = Mock(spec=ServicerContext)

                alice = get_alice_xmss()
                my_message = b'Hello xrd!'

                request = xrd_pb2.MessageTxnReq(
                    message=my_message,
                    fee=12,
                    xmss_pk=alice.pk
                )

                response = service.GetMessageTxn(request=request, context=context)
                context.set_code.assert_not_called()
                context.set_details.assert_not_called()

                self.assertIsNotNone(response)
                self.assertIsNotNone(response.extended_transaction_unsigned.tx)
                self.assertEqual('message', response.extended_transaction_unsigned.tx.WhichOneof('transactionType'))

                self.assertEqual(12, response.extended_transaction_unsigned.tx.fee)
                self.assertEqual(alice.pk, response.extended_transaction_unsigned.tx.public_key)
                self.assertEqual(0, response.extended_transaction_unsigned.tx.nonce)
                self.assertEqual(b'', response.extended_transaction_unsigned.tx.signature)
                self.assertEqual(b'', response.extended_transaction_unsigned.tx.transaction_hash)
                self.assertEqual(my_message, response.extended_transaction_unsigned.tx.message.message_hash)

                tmp_hash_pre = response.extended_transaction_unsigned.tx.master_addr
                tmp_hash_pre += response.extended_transaction_unsigned.tx.fee.to_bytes(8, byteorder='big', signed=False)
                tmp_hash_pre += response.extended_transaction_unsigned.tx.message.message_hash

                tmp_hash = sha256(tmp_hash_pre)
                hash_found = bin2hstr(Transaction.from_pbdata(response.extended_transaction_unsigned.tx).
                                      get_data_hash())
                self.assertEqual(hash_found,
                                 bin2hstr(tmp_hash))

                signed_transaction = response.extended_transaction_unsigned.tx
                signed_transaction.signature = alice.sign(tmp_hash)

                req_push = xrd_pb2.PushTransactionReq(transaction_signed=signed_transaction)

                resp_push = service.PushTransaction(req_push, context=context)
                context.set_code.assert_not_called()
                context.set_details.assert_not_called()

                self.assertIsNotNone(resp_push)
                self.assertEqual(xrd_pb2.PushTransactionResp.SUBMITTED,
                                 resp_push.error_code)
                self.assertEqual('b7ee814a548a6bbb8d97b2d3a0eb9e1f8b6ceee49b764e3c7b23d104aca6abeb',
                                 bin2hstr(resp_push.tx_hash))