Exemple #1
0
class TokenSyncBlockEosFromDbScript(object):
    mysql_tool = None
    mysql_dev_tool = None
    # slog = Slog("token_sync_block_eos_from_db_script")

    def __init__(self):
        self.mysql_tool = MysqlTools()
        mysql_dev_conf = get_mysql_conf(env="dev")
        # mysql_dev_conf["host"] = "luckypark0121.cnzvcx1qv3xd.us-east-2.rds.amazonaws.com"
        self.mysql_dev_tool = MysqlTools(mysql_dev_conf)

    def work(self, last_block_num=None):

        with self.mysql_dev_tool.session_scope() as dev_session:
            if not last_block_num:
                last_block_num_tuple = dev_session.query(SyncEosModel.block_num).order_by(SyncEosModel.block_num.desc()).first()
                if last_block_num_tuple:
                    last_block_num = last_block_num_tuple[_ZERO]
                else:
                    last_block_num = _ZERO
            with self.mysql_tool.session_scope() as session:
                tmp_block_detail_list = session.query(SyncEosModel).filter(SyncEosModel.block_num > last_block_num).all()
                if not tmp_block_detail_list:
                    return True
                dev_tmp_block_detail_list = []
                for tmp_block_detail in tmp_block_detail_list:
                    block_num = tmp_block_detail.block_num
                    block_hash = tmp_block_detail.block_hash
                    time_stamp = tmp_block_detail.time_stamp
                    time_stamp_decimal = tmp_block_detail.time_stamp_decimal
                    previous = tmp_block_detail.previous
                    status = tmp_block_detail.status
                    print("syncing block_num: " + str(block_num), "time_stamp: " + time_stamp)
                    dev_tmp_block_detail = SyncEosModel(
                        block_num=block_num,
                        block_hash=block_hash,
                        time_stamp=time_stamp,
                        time_stamp_decimal=time_stamp_decimal,
                        previous=previous,
                        status=status,
                    )
                    if len(dev_tmp_block_detail_list) <= _SIXTY:
                        dev_tmp_block_detail_list.append(dev_tmp_block_detail)
                    else:
                        dev_session.add_all(dev_tmp_block_detail_list)
                        dev_session.commit()
                        dev_tmp_block_detail_list = []

        return True
class WalletService(BaseService):
    symbol_to_token_coin = {
        _BTC: _COIN_ID_BTC,
        _ETH: _COIN_ID_ETH,
        _EOS: _COIN_ID_EOS
    }
    symbol_to_model = {
        _BTC: [
            WalletBtcModel, SecretBtcModel, WalletBtcGatherModel,
            SecretBtcGatherModel
        ],
        _ETH: [
            WalletEthModel, SecretEthModel, WalletEthGatherModel,
            SecretEthGatherModel
        ],
        _EOS: [
            WalletEosModel, SecretEosModel, WalletEosGatherModel,
            SecretEosGatherModel
        ],
    }
    _gather = "gather"
    _normal = "normal"
    interval = _HUNDRED * _ONE

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        wc = get_wallet_config(remove_type=False)
        self.wallet = None
        self.chain_model = None
        self.chain_token_model = None
        self.acct_pub_key_b58_aes = None
        self.coin_id = None
        self.symbol = wc["symbol"].upper()
        self.key = str(wc["key"])
        self.nonce = str(wc["nonce"])
        self.mnemonic = wc["mnemonic"]
        self.passphrase = wc["passphrase"]
        self.category = wc.get("category", self._normal).lower()
        self.mysql_token = MysqlTools(get_about_conf())
        self.mysql_wallet = MysqlTools()

    def wallet_init(self):
        """
        :return:
        """
        if self.symbol not in self.symbol_to_model or self.symbol not in self.symbol_to_token_coin:
            raise Exception("There is no corresponding symbol")
        if self.category == self._normal:
            token_model_index = _ZERO
            secret_model_index = _ONE
        elif self.category == self._gather:
            token_model_index = _TWO
            secret_model_index = _THREE
        else:
            raise Exception("The category does not exist")
        self.chain_token_model = self.symbol_to_model[
            self.symbol][token_model_index]
        self.chain_model = self.symbol_to_model[
            self.symbol][secret_model_index]
        self.wallet = Wallet(symbol=self.symbol)
        self.wallet.init_acct(self.mnemonic, self.passphrase)
        self.acct_pub_key_b58_aes = super_AES(
            self.wallet.get_acct_key()["acct_pub_key_b58"], self.key,
            self.nonce)
        # 查询 token_id
        self.coin_id = self.symbol_to_token_coin[self.symbol]
        with self.mysql_wallet.session_scope() as session:
            # 查询或插入 token_salt
            salt = session.query(TokenSaltModel).filter(
                TokenSaltModel.public_key_aes == self.acct_pub_key_b58_aes,
                TokenSaltModel.coin_id == self.coin_id).first()
            if not salt:
                new_salt = TokenSaltModel(
                    coin_id=self.coin_id,
                    public_key_aes=self.acct_pub_key_b58_aes,
                    key_aes=self.key,
                    nonce_aes=self.nonce)
                session.add(new_salt)
            else:
                if salt.key_aes != self.key or salt.nonce_aes != self.nonce:
                    raise Exception(
                        "Table token_salt contains this key nonce, results already generated cannot be replaced with new key or nonce"
                    )
            session.commit()

    def wallet_generate(self, count):
        """
        生成HD子钱包
        :param count: 生成的子钱包个数, 按index顺序生成, 接续数据库索引
        :return:
        """
        remainder = count % self.interval
        times = count // self.interval + _ONE if remainder else count // self.interval
        for num in range(_ONE, times + _ONE):
            count = self.interval
            if num == times:
                if remainder:
                    count = remainder
            # 获取数据库现有索引
            with self.mysql_wallet.session_scope() as session:
                wallets = session.query(self.chain_model).filter(
                    self.chain_model.acct_public_key_aes ==
                    self.acct_pub_key_b58_aes).with_for_update().order_by(
                        self.chain_model.sub_index.desc(),
                        self.chain_model._id.desc()).first()

                if not wallets:
                    begin = None
                else:
                    begin = int(wallets.sub_index) + _ONE
                print("-" * 20)
                print("The latest index is: " +
                      str(begin - _ONE) if begin else str(_ZERO))

                wallet_list, wallet_token_list = self.chain_model_generate(
                    count, begin)

                with self.mysql_token.session_scope() as session_token:
                    session_token.add_all(wallet_token_list)
                    session_token.commit()

                session.add_all(wallet_list)
                session.commit()
            print("Now we've successfully inserted: " + str(count) + "!!!")
            print("-" * 20)
        return True

    def chain_model_generate(self, count, begin):
        """
        批量生成chain model
        :param count:
        :param begin:
        :return: model list
        """

        sub_key = self.wallet.get_sub_key(count, begin)
        sub_key_aes = {}
        if self.symbol in [_BTC, _ETH]:
            for k, v in sub_key.items():
                sub_key_aes[k] = super_AES(v, self.key, self.nonce)
        elif self.symbol in [_EOS]:
            sub_key_aes = sub_key
        wallet_list = []
        wallet_token_list = []
        for sub_index, index_info in sub_key_aes.items():
            if self.symbol in [_EOS] and self.category == self._gather:
                index_info["sub_private_key"] = super_AES(
                    index_info["sub_private_key"], self.key, self.nonce)
                index_info["sub_address"] = self.mnemonic
            print('  change_index: ' + index_info["change_index"] +
                  " public_address: " + index_info["sub_address"])
            w = self.chain_model(
                sub_index=int(sub_index),
                change_index=index_info["change_index"],
                sub_private_key_aes=index_info["sub_private_key"],
                sub_public_key_aes=index_info["sub_public_key"],
                sub_public_address=index_info["sub_address"],
                acct_public_key_aes=self.acct_pub_key_b58_aes,
                coin_id=self.coin_id)
            w_token = self.chain_token_model(
                sub_index=int(sub_index),
                change_index=index_info["change_index"],
                sub_public_address=index_info["sub_address"],
                acct_public_key_aes=self.acct_pub_key_b58_aes,
                coin_id=self.coin_id)
            wallet_list.append(w)
            wallet_token_list.append(w_token)
        return wallet_list, wallet_token_list

    @staticmethod
    def generate_key_nonce(key, nonce):
        """
        transform origin args type
        :param key: must be origin
        :param nonce:
        :return:
        """
        return {"key": encode_str_hex(key), "nonce": encode_str_hex(nonce)}
class CentralService(BaseService):
    symbol_to_model = {
        _BTC: [WalletBtcModel, SecretBtcModel, SecretBtcGatherModel],
        _ETH: [WalletEthModel, SecretEthModel, SecretEthGatherModel],
    }
    _gather = "gather"
    _normal = "normal"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.mysql_token = MysqlTools(get_about_conf())
        self.coin_id = None

    def get_private_key_from_address(self, args):
        order_no = args["order_no"]
        coin_type = args["type"].upper()
        address = args["address"]
        category = args.get("category", self._normal)

        # 查询coin_id
        with self.mysql_token.session_scope() as session:
            # 查询 token_id
            token = session.query(TokenCoinModel).filter(
                TokenCoinModel.coin_name == coin_type).first()
            if not token:
                self.return_error(90002)
            self.coin_id = token.coin_id

        # 判断地址合法性
        if isinstance(address, str):
            address = [address]
        else:
            if not isinstance(address, list):
                self.return_error(90001)

        # 判断币种类型合法性
        if coin_type not in self.symbol_to_model:
            self.return_error(90002)

        # 判断地址类型合法性
        if category == self._normal:
            model_index = _ONE
            ret = {"category": self._normal}
        elif category == self._gather:
            model_index = _TWO
            ret = {"category": self._gather}
        else:
            self.return_error(90004)
            ret = {}
            model_index = _ZERO

        # 获取对应model
        chain_model = self.symbol_to_model[coin_type][model_index]

        # 地址转成字符串
        address_record = get_str_from_list(address)

        # 查询结果,并记录流水
        with MysqlTools().session_scope() as session:
            record = session.query(RecordPkModel).filter(
                RecordPkModel.order_no == order_no).first()
            if record:
                self.return_error(10008)

            wallets = session.query(chain_model).filter(
                chain_model.sub_public_address.in_(
                    address)).with_for_update().all()
            if not wallets:
                self.return_error(90003)

            for w in wallets:
                public_key_aes = w.acct_public_key_aes
                public_address = w.sub_public_address
                private_key_aes = w.sub_private_key_aes

                if public_key_aes not in ret:
                    ret[public_key_aes] = [{
                        "public_address": public_address,
                        "private_key_aes": private_key_aes,
                    }]
                else:
                    ret[public_key_aes].append({
                        "public_address":
                        public_address,
                        "private_key_aes":
                        private_key_aes,
                    })

            record_pk = RecordPkModel(order_no=order_no,
                                      coin_id=self.coin_id,
                                      address=address_record,
                                      response=json.dumps(ret),
                                      category=category)
            session.add(record_pk)
            session.commit()

        return ret