Exemplo n.º 1
0
    def decrypt(self, memo):
        """ Decrypt a memo

            :param str memo: encrypted memo message
            :returns: encrypted memo
            :rtype: str
        """
        if not memo:
            return None

        # We first try to decode assuming we received the memo
        try:
            memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey(
                memo["to"])
            pubkey = memo["from"]
        except KeyNotFound:
            try:
                # if that failed, we assume that we have sent the memo
                memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey(
                    memo["from"])
                pubkey = memo["to"]
            except KeyNotFound:
                # if all fails, raise exception
                raise MissingKeyError(
                    "Non of the required memo keys are installed!"
                    "Need any of {}".format([memo["to"], memo["from"]]))

        if not hasattr(self, 'chain_prefix'):
            self.chain_prefix = self.blockchain.prefix

        return BtsMemo.decode_memo(PrivateKey(memo_wif),
                                   PublicKey(pubkey, prefix=self.chain_prefix),
                                   memo.get("nonce"), memo.get("message"))
Exemplo n.º 2
0
    def decodeMemo(self, **kwargs):
        from_pubkey = kwargs.get('from')
        to_pubkey = kwargs.get('to')
        nonce = kwargs.get('nonce')
        cipher_text = kwargs.get('message')
        #		local_privkey = self.privkeys[0]
        if not isinstance(from_pubkey, PublicKey):
            from_pubkey = PublicKey(from_pubkey, prefix=from_pubkey[0:3])
        if not isinstance(to_pubkey, PublicKey):
            to_pubkey = PublicKey(to_pubkey, prefix=to_pubkey[0:3])
#		if str(self.pubkey) == str(from_pubkey):
#			other_pubkey = to_pubkey
#		elif str(self.pubkey) == str(to_pubkey):
#			other_pubkey = from_pubkey
        if str(from_pubkey) in self.privkeys:
            local_privkey = self.privkeys[str(from_pubkey)]
            other_pubkey = to_pubkey
        elif str(to_pubkey) in self.privkeys:
            local_privkey = self.privkeys[str(to_pubkey)]
            other_pubkey = from_pubkey
        else:
            raise MissingKey(
                "No Private Key found for neither %s nor %s public keys" %
                (str(from_pubkey), str(to_pubkey)))
        clear = BTSMemo.decode_memo(local_privkey, other_pubkey, nonce,
                                    cipher_text)
        return clear
Exemplo n.º 3
0
 def test_decrypt_bugged_padding(self):
     for memo in not_enough_padding:
         dec = decode_memo(
             PrivateKey(memo["wif"]),
             PublicKey(memo["to"], prefix="GPH"),
             memo["nonce"],
             memo["message"],
         )
         self.assertEqual(memo["plain"], dec)
Exemplo n.º 4
0
 def test_decrypt(self):
     for memo in test_cases:
         dec = decode_memo(
             PrivateKey(memo["wif"]),
             PublicKey(memo["to"], prefix="GPH"),
             memo["nonce"],
             memo["message"],
         )
         self.assertEqual(memo["plain"], dec)
Exemplo n.º 5
0
    def decrypt(self, memo):
        """ Decrypt a memo

            :param str memo: encrypted memo message
            :returns: encrypted memo
            :rtype: str
        """
        if not memo:
            return None

        memo_wif = self.bitshares.wallet.getPrivateKeyForPublicKey(
            self.to_account["options"]["memo_key"])
        if not memo_wif:
            raise MissingKeyError("Memo key for %s missing!" %
                                  self.to_account["name"])

        # TODO: Use pubkeys of the message, not pubkeys of account!
        return BtsMemo.decode_memo(
            PrivateKey(memo_wif),
            PublicKey(self.from_account["options"]["memo_key"],
                      prefix=self.bitshares.rpc.chain_params["prefix"]),
            memo.get("nonce"), memo.get("message"))
    def clean_txs(self, account: Account, symbol: str,
                  transactions: Iterable[dict]) -> Generator[dict, None, None]:
        """
        Filters a list of transactions by the receiving account, yields dict's conforming with
        :class:`payments.models.Deposit`

        :param str account: The 'to' account to filter by
        :param str symbol:  The symbol of the token being filtered
        :param list<dict> transactions:  A list<dict> of transactions to filter
        :return: A generator yielding ``dict`` s conforming to :class:`payments.models.Deposit`
        """
        for tx in transactions:
            try:
                data = tx['op'][
                    1]  # unwrap the transaction structure to get at the data within

                if data['to'] != account['id'] or data['from'] == account['id']:
                    continue

                # cache asset data for 5 mins, so we aren't spamming the RPC node for data
                amount_info = data['amount']
                asset_id = amount_info['asset_id']
                asset_key = 'btsasset:%s' % (asset_id, )
                asset = cache.get(asset_key, default=None)
                if asset is None:
                    asset_obj = self.get_asset_obj(asset_id)
                    if asset_obj is not None:
                        asset = {
                            'symbol': asset_obj.symbol,
                            'precision': asset_obj.precision
                        }
                        cache.set(asset_key, asset, 300)
                    else:
                        continue
                if asset['symbol'] != symbol:
                    continue

                raw_amount = Decimal(int(amount_info['amount']))
                transfer_quantity = raw_amount / (10**asset['precision'])

                # cache account data for 5 mins, so we aren't spamming the RPC node for data
                account_key = 'btsacc:%s' % (data['from'], )
                from_account_name = cache.get(account_key,
                                              default=data['from'])
                if from_account_name == data['from']:
                    from_account = self.get_account_obj(data['from'])
                    if from_account is not None:
                        from_account_name = from_account.name
                        cache.set(account_key, from_account_name, 300)
                    else:
                        log.exception(
                            'From account not found for transaction %s', tx)

                # decrypt the transaction memo
                memo_msg = ''
                if 'memo' in data:
                    memo = data['memo']
                    try:
                        memokey = self.get_private_key(account.name, 'memo')
                        privkey = PrivateKey(memokey)
                        pubkey = PublicKey(memo['from'], prefix='BTS')
                        memo_msg = decode_memo(privkey, pubkey, memo['nonce'],
                                               memo['message'])
                    except Exception as e:
                        memo_msg = '--cannot decode memo--'
                        log.exception(
                            'Error decoding memo %s, got exception %s',
                            memo['message'], e)

                # fetch timestamp from the block containing this transaction
                # (a hugely inefficient lookup but unfortunately no other way to do this)
                tx_datetime = datetime.fromtimestamp(
                    self.get_block_timestamp(tx['block_num']))
                tx_datetime = timezone.make_aware(tx_datetime, pytz.UTC)

                clean_tx = dict(txid=tx['id'],
                                coin=self.coins[symbol].symbol,
                                tx_timestamp=tx_datetime,
                                from_account=from_account_name,
                                to_account=account.name,
                                memo=memo_msg,
                                amount=transfer_quantity)
                yield clean_tx
            except Exception as e:
                log.exception(
                    'Error parsing transaction data. Skipping this TX. tx = %s, exception = %s',
                    tx, e)
                continue
Exemplo n.º 7
0
def decrypt_msg(priv_key, pub_key, nonce, msg):
    dec = decode_memo(PrivateKey(priv_key), PublicKey(pub_key, prefix="NEST"),
                      nonce, msg)
    return dec
Exemplo n.º 8
0
    async def process_operations(self, op_id):
        """ 处理操作
        """
        op_info = await self.node_api.get_objects([op_id])
        for operation in op_info[::-1]:
            if operation["op"][0] != 0:
                return

            # 操作基本信息
            trx = {}
            op = operation['op'][1]
            trx['trx_id'] = operation['id']

            # 获取区块信息
            trx['block_num'] = operation['block_num']
            block_info = await self.node_api.get_block(trx['block_num'])
            trx['timestamp'] = block_info['timestamp']

            # 获取转账金额
            asset = await self.get_asset_info(op['amount']['asset_id'])
            trx['asset'] = asset['symbol']
            trx['asset_id'] = op['amount']['asset_id']
            trx['amount'] = float(op['amount']['amount']) / float(10**int(
                asset['precision']))

            # 获取转账手续费
            trx['fee'] = {}
            fee = await self.get_asset_info(op['fee']['asset_id'])
            trx['fee']['asset'] = fee['symbol']
            trx['fee']['asset_id'] = op['fee']['asset_id']
            trx['fee']['amount'] = float(op['fee']['amount']) / float(10**int(
                fee['precision']))

            # 获取涉案账户
            trx['to_id'] = op['to']
            trx['from_id'] = op['from']
            trx['to'] = (await
                         self.node_api.get_objects([op['to']]))[0]['name']
            trx['from'] = (await
                           self.node_api.get_objects([op['from']]))[0]['name']

            # 解码备注信息
            if 'memo' in op:
                memo = op['memo']
                trx['nonce'] = memo['nonce']
                try:
                    privkey = PrivateKey(self.wifkey)
                    prefix = self.node_api.chain_params['prefix']
                    if trx['to_id'] == self.account['id']:
                        pubkey = PublicKey(memo['from'], prefix=prefix)
                    else:
                        pubkey = PublicKey(memo['to'], prefix=prefix)
                    trx['memo'] = BtsMemo.decode_memo(privkey, pubkey,
                                                      memo['nonce'],
                                                      memo['message'])
                except Exception:
                    trx['memo'] = None
            else:
                trx['memo'] = None
                trx['nonce'] = None

            # 触发转账事件
            if trx['from_id'] == self.account['id']:
                await self.on_sent(trx)
            elif trx['to_id'] == self.account['id']:
                await self.on_receive(trx)
Exemplo n.º 9
0
    async def _process_transfer_operations(self, client, operation):
        ''' 处理转账操作
        '''
        # 筛选操作类型
        if operation['op'][0] != self.TRANSFER_OPERATION:
            return

        # 操作基本信息
        trx = {}
        op = operation['op'][1]

        # 获取区块信息
        trx['heigth'] = operation['block_num']
        block_info = await client.get_block(trx['heigth'])
        trx['timestamp'] = block_info['timestamp']

        # 获取交易ID
        trx_in_block = operation['trx_in_block']
        transaction = block_info['transactions'][trx_in_block]
        trx['txid'] = await self._get_transaction_id(transaction)

        # 获取转账金额
        asset = await self._get_asset_info(client, op['amount']['asset_id'])
        trx['asset'] = asset['symbol']
        trx['asset_id'] = op['amount']['asset_id']
        trx['amount'] = str(
            float(op['amount']['amount']) / float(10**int(asset['precision'])))

        # 获取转账手续费
        trx['fee'] = {}
        fee = await self._get_asset_info(client, op['fee']['asset_id'])
        trx['fee']['asset'] = fee['symbol']
        trx['fee']['asset_id'] = op['fee']['asset_id']
        trx['fee']['amount'] = str(
            float(op['fee']['amount']) / float(10**int(fee['precision'])))

        # 获取涉案账户
        trx['to_id'] = op['to']
        trx['from_id'] = op['from']
        trx['to'] = (await client.get_objects([op['to']]))[0]['name']
        trx['from'] = (await client.get_objects([op['from']]))[0]['name']

        # 解码备注信息
        if 'memo' in op:
            memo = op['memo']
            trx['nonce'] = memo['nonce']
            try:
                privkey = PrivateKey(SysConfig().memo_key)
                prefix = client.chain_params['prefix']
                if trx['to_id'] == self._account['id']:
                    pubkey = PublicKey(memo['from'], prefix=prefix)
                else:
                    pubkey = PublicKey(memo['to'], prefix=prefix)
                trx['memo'] = BtsMemo.decode_memo(privkey, pubkey,
                                                  memo['nonce'],
                                                  memo['message'])
            except Exception as e:
                logging.warn('Failed to decode memo, %s, %s', operation['id'],
                             str(e))
                trx['memo'] = None
        else:
            trx['memo'] = None
            trx['nonce'] = None
        return trx
Exemplo n.º 10
0
            json.dumps(trx, indent=4)))
        return False


for f in account_history_b20:

    if not is_valid_bit20_publication(f):
        print('Hijacking attempt of the bit20 feed? trx: {}'.format(
            json.dumps(f, indent=4)))
        continue

    memo = f['op'][1]['memo']

    privkey = PrivateKey(wifkey_announce)
    pubkey = PublicKey(Account(f['op'][1]['from'])['options']['memo_key'])
    memomsg = BtsMemo.decode_memo(privkey, pubkey, memo["nonce"],
                                  memo["message"])

    #print(memomsg)
    if memomsg.startswith('COMPOSITION'):
        # last_updated = re.search('\((.*)\)', memomsg)
        # if last_updated:
        #     last_updated = pendulum.from_format(last_updated.group(1), '%Y/%m/%d')
        #     #print(last_updated)
        bit20 = json.loads(memomsg.split(')', maxsplit=1)[1])
        break

else:
    print(
        "Did not find any bit20 composition in the last {} messages to account bittwenty.feed"
        .format(len(bit20feed)))