Esempio n. 1
0
    async def _send_block_create(self,
                                 amount: int,
                                 destination: str,
                                 id: str = None,
                                 work: str = None) -> dict:
        """Create a state block (send)"""
        # Get account info
        is_open = True
        account_info = await RPCClient.instance().account_info(
            self.account.address)
        if account_info is None:
            return None

        # Check balance
        if amount > int(account_info['balance']):
            # Auto-receive blocks if they have it pending
            if config.Config.instance().auto_receive_on_send and int(
                    account_info['balance']) + int(
                        account_info['pending']) >= amount:
                await self._receive_all()
                account_info = await RPCClient.instance().account_info(
                    self.account.address)
                if account_info is None:
                    return None
                if amount > int(account_info['balance']):
                    raise InsufficientBalance(account_info['balance'])
            else:
                raise InsufficientBalance(account_info['balance'])

        workbase = account_info['frontier']

        # Build other fields
        previous = account_info['frontier']
        representative = account_info['representative']
        balance = str(int(account_info['balance']) - amount)

        # Generate work
        if work is None:
            try:
                work = await WorkClient.instance().work_generate(workbase)
                if work is None:
                    raise WorkFailed(workbase)
            except Exception:
                raise WorkFailed(workbase)

        # Build final state block
        state_block = nanopy.state_block()
        state_block['account'] = self.account.address
        state_block['previous'] = previous
        state_block['representative'] = representative
        state_block['balance'] = balance
        state_block['link'] = nanopy.account_key(destination)
        state_block['work'] = work

        # Sign block
        pk = self.private_key()
        state_block['signature'] = await nano_util.NanoUtil.instance(
        ).sign_block(pk, block=state_block)

        return state_block
Esempio n. 2
0
    async def _receive_block_create(self, hash: str, work: str = None) -> dict:
        """Build a state block (receive)"""
        # Get block info
        block_info = await RPCClient.instance().block_info(hash)
        if block_info is None or block_info['contents'][
                'link_as_account'] != self.account.address:
            return None
        # Get account info
        is_open = True
        try:
            account_info = await RPCClient.instance().account_info(
                self.account.address)
            if account_info is None:
                return None
        except AccountNotFound:
            is_open = False

        # Different workbase for open/receive
        if is_open:
            workbase = account_info['frontier']
        else:
            workbase = nanopy.account_key(self.account.address)

        # Build other fields
        previous = '0000000000000000000000000000000000000000000000000000000000000000' if not is_open else account_info[
            'frontier']
        representative = self.get_representative(
        ) if not is_open else account_info['representative']
        balance = block_info['amount'] if not is_open else str(
            int(account_info['balance']) + int(block_info['amount']))

        # Generate work
        if work is None:
            try:
                work = await WorkClient.instance().work_generate(
                    workbase,
                    DifficultyModel.instance().receive_difficulty)
                if work is None:
                    log.server_logger.error("WORK FAILED")
                    raise WorkFailed(workbase)
            except Exception:
                log.server_logger.exception("work failed")
                raise WorkFailed(workbase)

        # Build final state block
        state_block = nanopy.state_block()
        state_block['account'] = self.account.address
        state_block['previous'] = previous
        state_block['representative'] = representative
        state_block['balance'] = balance
        state_block['link'] = hash
        state_block['work'] = work

        # Sign block
        pk = self.private_key()
        state_block['signature'] = await nano_util.NanoUtil.instance(
        ).sign_block(pk, block=state_block)

        return state_block
Esempio n. 3
0
    async def _change_block_create(self,
                                   representative: str,
                                   work: str = None,
                                   only_if_different: bool = False) -> dict:
        """Create a state block (change)"""
        # Get account info
        account_info = await RPCClient.instance().account_info(
            self.account.address)
        if account_info is None:
            return None
        elif only_if_different and account_info[
                'representative'] == representative:
            return None

        workbase = account_info['frontier']

        # Build other fields
        previous = account_info['frontier']
        representative = representative
        balance = account_info['balance']

        # Generate work
        if work is None:
            try:
                work = await WorkClient.instance().work_generate(
                    workbase,
                    DifficultyModel.instance().send_difficulty)
                if work is None:
                    raise WorkFailed(workbase)
            except Exception:
                raise WorkFailed(workbase)

        # Build final state block
        state_block = nanopy.state_block()
        state_block['account'] = self.account.address
        state_block['previous'] = previous
        state_block['representative'] = representative
        state_block['balance'] = balance
        state_block[
            'link'] = '0000000000000000000000000000000000000000000000000000000000000000'
        state_block['work'] = work

        # Sign block
        pk = self.private_key()
        state_block['signature'] = await nano_util.NanoUtil.instance(
        ).sign_block(pk, block=state_block)

        return state_block