def create_vote_transaction(input_private_key: str, candidates_list: list, amount: int, rpc_port: int, vote_content):
    # check output
    if candidates_list is None or len(candidates_list) == 0:
        Logger.error("Invalid output addresses")
        return None

    # candidates_bytes_list = list()
    #
    # for candidate in candidates_list:
    #     candidates_bytes_list.append(bytes.fromhex(candidate))

    # create outputs
    account = Account(input_private_key)
    outputs = create_vote_output(account.address(), amount, vote_content)

    # create inputs
    total_amount = amount + util.TX_FEE
    inputs, change_outputs = create_normal_inputs(account.address(), total_amount, rpc_port)
    if inputs is None or change_outputs is None:
        Logger.error("Create normal inputs failed")
        return None
    outputs.extend(change_outputs)

    # create program
    programs = list()
    redeem_script = bytes.fromhex(account.redeem_script())
    program = Program(code=redeem_script, params=None)
    programs.append(program)

    # create attributes
    attributes = list()
    attribute = Attribute(
        usage=Attribute.NONCE,
        data=bytes("attributes".encode())
    )
    attributes.append(attribute)

    tx = Transaction()
    tx.version = Transaction.TX_VERSION_09
    tx.tx_type = Transaction.TRANSFER_ASSET
    tx.payload = Payload(Payload.DEFAULT_VERSION)
    tx.attributes = attributes
    tx.inputs = inputs
    tx.outputs = outputs
    tx.lock_time = 0
    tx.programs = programs

    return tx
Esempio n. 2
0
    def transfer_multi_cross_chain_asset(self, input_private_key: str,
                                         lock_address: str, cross_address: str,
                                         tx_count: int, amount: int,
                                         recharge: bool, port: int):
        account = Account(input_private_key)
        response = rpc.list_unspent_utxos(account.address(), port=port)
        if not response or isinstance(response, dict):
            Logger.error("get utxos return error: {}".format(response))
            return False
        utxos = response
        if len(utxos) < tx_count:
            Logger.error("utxo is not enough")
            return False

        for i in range(tx_count):
            current_utxos = list()
            utxo = utxos[i]
            current_utxos.append(utxo)
            Logger.info("current cross chain index: {}".format(i))
            tx = txbuild.create_cross_chain_transaction_by_utxo(
                input_private_key=input_private_key,
                lock_address=lock_address,
                cross_chain_address=cross_address,
                amount=amount,
                recharge=recharge,
                utxos=current_utxos)

            if tx is None:
                return False

            tx = txbuild.single_sign_transaction(input_private_key, tx)
            Logger.debug("cross chain asset transaction: \n{}".format(tx))
            ret = self.handle_tx_result(tx, port)

        return ret
def create_crc_proposal_tracking_transaction(input_private_key: str, amount: int, payload: CRCProposalTracking,
                                             rpc_port: int):
    # create outputs
    account = Account(input_private_key)
    outputs, total_amount = create_normal_outputs(
        output_addresses=[account.address()],
        amount=amount,
        fee=util.TX_FEE,
        output_lock=0
    )

    # create inputs
    inputs, change_outputs = create_normal_inputs(account.address(), total_amount, rpc_port)
    if inputs is None or change_outputs is None:
        Logger.error("Create normal inputs failed")
        return None
    outputs.extend(change_outputs)

    # create program
    programs = list()
    redeem_script = bytes.fromhex(account.redeem_script())
    program = Program(code=redeem_script, params=None)
    programs.append(program)

    # create attributes
    attributes = list()
    attribute = Attribute(
        usage=Attribute.NONCE,
        data=bytes("attributes".encode())
    )
    attributes.append(attribute)

    tx = Transaction()
    tx.version = Transaction.TX_VERSION_09
    tx.tx_type = Transaction.CRC_PROPOSAL_TRACKING
    tx.payload_version = 0
    tx.payload = payload
    tx.attributes = attributes
    tx.inputs = inputs
    tx.outputs = outputs
    tx.lock_time = 0
    tx.programs = programs

    return tx
def create_transaction(input_private_key: str, output_addresses: list, amount: int, rpc_port: int, side_chain: bool):
    account = Account(input_private_key)
    # check output
    if output_addresses is None or len(output_addresses) == 0:
        Logger.error("Invalid output addresses")
        return None

    # create outputs
    outputs, total_amount = create_normal_outputs(
        output_addresses=output_addresses,
        amount=amount,
        fee=util.TX_FEE,
        output_lock=0
    )

    # create inputs
    inputs, change_outputs = create_normal_inputs(account.address(), total_amount, rpc_port)

    if inputs is None or change_outputs is None:
        Logger.error("Create normal inputs failed")
        return None
    outputs.extend(change_outputs)

    # create program
    programs = list()
    redeem_script = bytes.fromhex(account.redeem_script())
    program = Program(code=redeem_script, params=None)
    programs.append(program)

    # create attributes
    attributes = list()
    attribute = Attribute(
        usage=Attribute.NONCE,
        data=bytes("attributes".encode())
    )
    attributes.append(attribute)

    tx = Transaction()
    if not side_chain :
        tx.version = Transaction.TX_VERSION_09
    else:
        tx.version = Transaction.TX_VERSION_DEFAULT

    tx.tx_type = Transaction.TRANSFER_ASSET
    tx.payload = Payload(Payload.DEFAULT_VERSION)
    tx.attributes = attributes
    tx.inputs = inputs
    tx.outputs = outputs
    tx.lock_time = 0
    tx.programs = programs

    return tx
    def _create_account_data(self, account: Account, account_type: str):
        private_key_encrypted = keytool.encrypt_private_key(
            self._master_key, bytes.fromhex(account.private_key()),
            account.ecc_public_key(), self._iv)

        account_data = dict()
        account_data["Address"] = account.address()
        account_data["ProgramHash"] = account.program_hash()
        account_data["RedeemScript"] = account.redeem_script()
        account_data["PrivateKeyEncrypted"] = private_key_encrypted.hex()
        account_data["Type"] = account_type

        return account_data
def create_cancel_transaction(input_private_key: str, payload: ProducerInfo, rpc_port: int):
    # create inputs
    account = Account(input_private_key)
    inputs, change_outputs = create_normal_inputs(account.address(), util.TX_FEE, rpc_port)
    if inputs is None or change_outputs is None:
        Logger.error("Create normal inputs failed")
        return None

    # create outputs
    outputs = list()
    outputs.extend(change_outputs)

    # create program
    programs = list()
    redeem_script = bytes.fromhex(account.redeem_script())
    program = Program(code=redeem_script, params=None)
    programs.append(program)

    # create attributes
    attributes = list()
    attribute = Attribute(
        usage=Attribute.NONCE,
        data=bytes("attributes".encode())
    )
    attributes.append(attribute)

    payload = ProcessProducer(bytes.fromhex(payload.owner_account.public_key()),
                              bytes.fromhex(payload.owner_account.private_key()))
    tx = Transaction()
    tx.version = Transaction.TX_VERSION_09
    tx.tx_type = Transaction.CANCEL_PRODUCER
    tx.payload_version = 0
    tx.payload = payload
    tx.attributes = attributes
    tx.inputs = inputs
    tx.outputs = outputs
    tx.lock_time = 0
    tx.programs = programs

    return tx
def create_cr_update_transaction(input_private_key: str, update_payload: CRInfo, rpc_port: int):
    # create inputs
    account = Account(input_private_key)
    inputs, change_outputs = create_normal_inputs(account.address(), util.TX_FEE, rpc_port)
    if inputs is None or change_outputs is None:
        Logger.error("Create normal inputs failed")
        return None

    # create outputs
    outputs = list()
    outputs.extend(change_outputs)

    # create program
    programs = list()
    redeem_script = bytes.fromhex(account.redeem_script())
    program = Program(code=redeem_script, params=None)
    programs.append(program)

    # create attributes
    attributes = list()
    attribute = Attribute(
        usage=Attribute.NONCE,
        data=bytes("attributes".encode())
    )
    attributes.append(attribute)

    # update_payload.gen_signature()

    tx = Transaction()
    tx.version = Transaction.TX_VERSION_09
    tx.tx_type = Transaction.UPDATE_CR
    tx.payload_version = 0
    tx.payload = update_payload
    tx.attributes = attributes
    tx.inputs = inputs
    tx.outputs = outputs
    tx.lock_time = 0
    tx.programs = programs

    return tx
def create_cross_chain_transaction_by_utxo(input_private_key: str, lock_address: str, cross_chain_address: str, amount: int,
                                   recharge: bool, utxos: list):
    if lock_address is None or lock_address is "":
        Logger.error("Invalid lock address")
        return None

    if cross_chain_address is None or cross_chain_address is "":
        Logger.error("Invalid cross chain address")
        return None

    account = Account(input_private_key)
    # create outputs:
    outputs, total_amount = create_normal_outputs(
        output_addresses=[lock_address],
        amount=amount,
        fee=util.TX_FEE,
        output_lock=0
    )

    # create inputs:
    inputs, change_outputs = create_normal_inputs_by_utxo(
        account.address(), total_amount, utxos)
    if inputs is None or change_outputs is None:
        Logger.error("Create normal inputs failed")
        return None
    outputs.extend(change_outputs)

    # create program
    programs = list()
    redeem_script = bytes.fromhex(account.redeem_script())
    program = Program(code=redeem_script, params=None)
    programs.append(program)

    # create attributes
    attributes = list()
    attribute = Attribute(
        usage=Attribute.NONCE,
        data=bytes("attributes".encode())
    )
    attributes.append(attribute)

    cross_chain_asset = TransferCrossChainAsset()
    cross_chain_asset.cross_chain_addresses = [cross_chain_address]
    cross_chain_asset.output_indexes = [0]
    cross_chain_asset.cross_chain_amounts = [amount - 10000]

    tx = Transaction()
    if recharge:
        tx.version = Transaction.TX_VERSION_09
    else:
        tx.version = Transaction.TX_VERSION_DEFAULT

    # Logger.debug("transaction version {}".format(tx.version))
    tx.tx_type = Transaction.TRANSFER_CROSS_CHAIN_ASSET
    tx.payload = cross_chain_asset
    tx.attributes = attributes
    tx.inputs = inputs
    tx.outputs = outputs
    tx.lock_time = 0
    tx.programs = programs

    return tx
Esempio n. 9
0
class Proposal(object):
    def __init__(self, input_private_key: str, node: ElaNode, nick_name: str,
                 url: str, location: int, net_address: str):

        self.input_private_key = input_private_key
        self.input = Account(input_private_key)
        self.node = node
        self.utxo_value = 0
        self.fee = 10000
        self.state = ""
        self.deposit_amount = 5000 * util.TO_SELA
        self.info = self._producer_info(self.node.owner_account,
                                        self.node.node_account, nick_name, url,
                                        location, net_address)

    @staticmethod
    def _producer_info(owner_account: Account, node_account: Account,
                       nick_name: str, url: str, location: int,
                       net_address: str):
        info = ProducerInfo(owner_account=owner_account,
                            node_account=node_account,
                            nickname=nick_name,
                            url=url,
                            location=location,
                            net_address=net_address)
        return info

    def producer_info(self):
        return self.info

    def input_account(self):
        return self.input

    def owner_account(self):
        return self.node.owner_account

    def node_account(self):
        return self.node.node_account

    def register(self, rpc_port: int):
        tx = txbuild.create_register_transaction(
            input_private_key=self.input_private_key,
            amount=self.deposit_amount,
            payload=self.info,
            rpc_port=rpc_port)

        if tx is None:
            return None

        tx = txbuild.single_sign_transaction(self.input_private_key, tx)

        return tx

    def update(self, producer_info: ProducerInfo, rpc_port: int):
        tx = txbuild.create_update_transaction(
            input_private_key=self.input_private_key,
            payload=producer_info,
            rpc_port=rpc_port)

        if tx is None:
            return None
        producer_info.gen_signature()
        tx = txbuild.single_sign_transaction(self.input_private_key, tx)

        return tx

    def cancel(self, rpc_port: int):
        tx = txbuild.create_cancel_transaction(
            input_private_key=self.input_private_key,
            payload=self.producer_info(),
            rpc_port=rpc_port)

        if tx is None:
            return None

        tx = txbuild.single_sign_transaction(self.input_private_key, tx)

        return tx

    def redeem(self, amount: int, rpc_port: int):

        tx = txbuild.create_redeem_transaction(
            payload=self.producer_info(),
            output_address=self.input.address(),
            amount=amount,
            rpc_port=rpc_port)

        if tx is None:
            return None

        tx = txbuild.single_sign_transaction(
            self.producer_info().owner_account.private_key(), tx)

        return tx

    def active(self):

        # note activate producer transaction needn't to sign the whole transaction
        tx = txbuild.create_active_transaction(
            self.node_account().private_key(),
            self.node_account().public_key())

        if tx is None:
            return None

        return tx

    def __repr__(self):
        return self.producer_info().__repr__()
class Controller(object):
    PRODUCER_STATE_ACTIVE = "Active"
    PRODUCER_STATE_INACTIVE = "Inactive"

    # CR_Foundation_TEMP = "EULhetag9FKS6Jd6aifFaPqjFTpZbSMY7u"
    CR_Foundation_TEMP = "CRASSETSXXXXXXXXXXXXXXXXXXXX2qDX5J"
    SECRETARY_PRIVATE_KEY = "E0076A271A137A2BD4429FA46E79BE3E10F2A730585F8AC2763D570B60469F11"
    CRC_COMMITTEE_ADDRESS = "CREXPENSESXXXXXXXXXXXXXXXXXX4UdT6b"

    def __init__(self, up_config: dict):
        self.tag = util.tag_from_path(__file__, Controller.__name__)

        # set config
        self.up_config = up_config
        self.root_path = os.path.abspath(
            os.path.join(os.path.abspath(__file__), "../../../"))
        self.config = util.read_config_file(
            os.path.join(self.root_path, "config.json"))
        self.node_types = ["ela", "arbiter", "did", "token", "neo"]
        self.reset_config(up_config)

        self.params = Parameter(self.config, self.root_path)
        self.check_params()
        self.env_manager = EnvManager()
        self.keystore_manager = KeyStoreManager(self.params)

        self.node_manager = NodeManager(self.params, self.env_manager,
                                        self.keystore_manager)
        self.tx_manager = TransactionManager(self.node_manager)
        # init tap amount and register amount(unit: ELA)
        self.tap_amount = 20000000
        self.register_amount = 6000
        self.node_amount = 5000
        # necessary keystore
        self.foundation_account = self.keystore_manager.foundation_account
        self.tap_account = self.keystore_manager.tap_account
        # pressure keystore
        self.pressure_account = Account()
        self.init_for_testing()
        self.later_nodes = self.node_manager.ela_nodes[(
            self.params.ela_params.number -
            self.params.ela_params.later_start_number + 1):]

        self.dpos_votes_dict = dict()
        self.crc_proposal_hash = bytes()
        self.owner_private_key = None
        self.secretary_private_key = self.SECRETARY_PRIVATE_KEY

    def init_for_testing(self):
        self.node_manager.deploy_nodes()
        Logger.info("{} deploying nodes on success!".format(self.tag))
        self.node_manager.start_nodes()
        self.node_manager.create_address_name_dict()
        self.node_manager.create_owner_pubkey_name_dict()
        self.node_manager.create_node_pubkey_name_dict()
        self.node_manager.create_normal_dpos_pubkey()
        Logger.info("{} starting nodes on success!".format(self.tag))
        self.mining_blocks_ready(self.foundation_account.address())
        Logger.info("{} mining 110 blocks on success!".format(self.tag))
        time.sleep(5)

        ret = self.tx_manager.recharge_necessary_keystore(
            input_private_key=self.foundation_account.private_key(),
            accounts=[self.tap_account],
            amount=self.tap_amount * constant.TO_SELA)

        self.check_result("recharge tap keystore", ret)

        Logger.info("{} recharge tap keystore {} ELAs on success!".format(
            self.tag, self.tap_amount * constant.TO_SELA))

        ret = self.tx_manager.recharge_necessary_keystore(
            input_private_key=self.tap_account.private_key(),
            accounts=self.keystore_manager.owner_accounts,
            amount=self.register_amount * constant.TO_SELA)

        self.check_result("recharge owner keystore", ret)

        ret = self.tx_manager.recharge_necessary_keystore(
            input_private_key=self.tap_account.private_key(),
            accounts=self.keystore_manager.node_accounts,
            amount=self.node_amount * constant.TO_SELA)

        self.check_result("recharge node keystore", ret)

        Logger.info("{} recharge producer on success!".format(self.tag))

        if self.params.arbiter_params.enable:
            ret = self.tx_manager.recharge_necessary_keystore(
                input_private_key=self.tap_account.private_key(),
                accounts=self.keystore_manager.sub1_accounts,
                amount=3 * constant.TO_SELA)
            self.check_result("recharge sub1 keystore", ret)
            Logger.info("{} recharge each sub1 keystore {} ELAs on success!")

            ret = self.tx_manager.recharge_necessary_keystore(
                input_private_key=self.tap_account.private_key(),
                accounts=self.keystore_manager.sub2_accounts,
                amount=3 * constant.TO_SELA)
            self.check_result("recharge sub2 keystore", ret)
            Logger.info("{} recharge each sub2 keystore {} ELAs on success!")

            ret = self.tx_manager.recharge_necessary_keystore(
                input_private_key=self.tap_account.private_key(),
                accounts=self.keystore_manager.sub3_accounts,
                amount=3 * constant.TO_SELA)
            self.check_result("recharge sub3 keystore", ret)
            Logger.info("{} recharge each sub3 keystore {} ELAs on success!")

            ret = self.tx_manager.recharge_necessary_keystore(
                input_private_key=self.tap_account.private_key(),
                accounts=self.keystore_manager.sub4_accounts,
                amount=3 * constant.TO_SELA)
            self.check_result("recharge sub4 keystore", ret)
            Logger.info("{} recharge each sub4 keystore {} ELAs on success!")

    def ready_for_pressure_inputs(self, inputs_num: int):
        ret = self.pressure_inputs(inputs_num)
        self.check_result("pressure inputs number:{}".format(inputs_num), ret)
        Logger.info("{}pressure inputs on success!".format(self.tag))

    def ready_for_pressure_big_block(self, data_size: int):
        ret = self.pressure_big_block(data_size)
        self.check_result("pressure big block size:{} ".format(data_size), ret)
        Logger.info("{}pressure big block on success!".format(
            self.tag, data_size))

    def pressure_inputs(self, inputs_num: int):
        output_addresses = list()
        for i in range(inputs_num):
            output_addresses.append(self.pressure_account.address())
        ret = self.tx_manager.transfer_asset(self.tap_account.private_key(),
                                             output_addresses,
                                             1 * util.TO_SELA)
        if ret:
            self.wait_block()
            value = rpc.get_balance_by_address(self.pressure_account.address())
            Logger.debug("{} account {} wallet balance: {}".format(
                self.tag, self.pressure_account.address(), value))

            ret = self.tx_manager.transfer_asset(
                self.pressure_account.private_key(),
                [self.pressure_account.address()],
                int(Decimal(value) * util.TO_SELA - util.TX_FEE))
            if ret:
                self.wait_block()
                return True
            else:
                Logger.error("{} pressure inputs transfer failed".format(
                    self.tag))
                return False
        else:
            Logger.error("{} pressure outupts transfer failed".format(
                self.tag))

        return ret

    def pressure_big_block(self, data_size):
        attributes = list()
        attribute = Attribute(usage=Attribute.NONCE,
                              data=Random.get_random_bytes(data_size))
        attributes.append(attribute)
        ret = self.tx_manager.transfer_abnormal_asset(
            self.tap_account.private_key(), [self.tap_account.address()],
            1 * util.TO_SELA,
            attributes=attributes)
        if ret:
            self.wait_block()
            return True
        else:
            Logger.error("{} pressure big block transfer failed".format(
                self.tag))
            return False

    def wait_block(self):
        Logger.info("waiting for the block ... ")
        count_height = 0
        height = self.get_current_height()
        while True:
            if height + 1 >= count_height:
                rpc.discrete_mining(1)
                time.sleep(1)
                count_height = self.get_current_height()
            else:
                break

    def ready_for_dpos(self):
        ret = self.tx_manager.register_producers_candidates()
        self.check_result("register producers", ret)
        Logger.info("{} register producers on success!".format(self.tag))
        ret = self.tx_manager.vote_producers_candidates()
        self.check_result("vote producers", ret)
        Logger.info("{} vote producer on success!".format(self.tag))
        self.get_dpos_votes()

    def ready_for_cr(self):
        ret = self.register_cr_candidates()
        self.get_current_height()
        self.check_result("register cr", ret)
        Logger.info("{} register cr on success!".format(self.tag))

        ret = self.tx_manager.vote_cr_candidates()
        self.get_current_height()
        self.check_result("vote cr", ret)
        Logger.info("{} vote cr on success!".format(self.tag))

        # transfer to CRFoundation
        # self.tx_manager.transfer_asset(self.tap_account.private_key(), [self.CR_Foundation_TEMP], 5000 * util.TO_SELA)
        # if ret:
        #     rpc.discrete_mining(1)
        #     value = rpc.get_balance_by_address(self.CR_Foundation_TEMP)
        #     Logger.debug("{} CRFoundation {} wallet balance: {}".format(self.tag, self.CR_Foundation_TEMP, value))
        # else:
        #     Logger.error("{} CRFoundation transfer failed".format(self.tag))
        self.tx_manager.transfer_asset(self.tap_account.private_key(),
                                       [self.CRC_COMMITTEE_ADDRESS],
                                       5000 * util.TO_SELA)
        if ret:
            rpc.discrete_mining(1)
            value = rpc.get_balance_by_address(self.CRC_COMMITTEE_ADDRESS)
            Logger.debug("{} CRFoundation {} wallet balance: {}".format(
                self.tag, self.CRC_COMMITTEE_ADDRESS, value))
        else:
            Logger.error("{} CRFoundation transfer failed".format(self.tag))

    def ready_for_crc_proposal(self):
        ret = self.crc_proposal()
        self.get_current_height()
        self.check_result("crc proposal", ret)
        Logger.info("{} crc proposal on success!".format(self.tag))

    def ready_for_crc_proposal_secretary_general(self):
        ret = self.crc_proposal_secretary_general()
        self.get_current_height()
        self.check_result("crc proposal change secretary general", ret)
        Logger.info(
            "{} crc proposal change secretary general on success!".format(
                self.tag))

    def ready_for_crc_proposal_change_owner(self):
        ret = self.crc_proposal_change_owner()
        self.get_current_height()
        self.check_result("crc proposal change owner", ret)
        Logger.info("{} crc proposal change owneron success!".format(self.tag))

    def ready_for_crc_proposal_review(self):
        ret = self.crc_proposal_review()
        self.get_current_height()
        self.check_result("crc proposal review", ret)
        Logger.info("{} crc proposal review on success!".format(self.tag))
        self.discrete_miner(self.params.ela_params.proposal_cr_voting_period)

        ret = self.tx_manager.vote_crc_proposal_candidates(
            self.crc_proposal_hash)
        self.get_current_height()
        self.check_result("vote cr proposal", ret)
        Logger.info("{} vote crc proposal  on success!".format(self.tag))
        self.discrete_miner(
            self.params.ela_params.proposal_public_voting_period)

    def ready_for_crc_proposal_tracking(self):
        # common
        ret = self.crc_proposal_tracking(None, CRCProposalTracking.COMMON, 0)
        self.get_current_height()
        self.check_result("crc proposal tracking common type", ret)
        Logger.info("{} crc proposal tracking common on success!".format(
            self.tag))

        # progress
        ret = self.crc_proposal_tracking(None, CRCProposalTracking.PROGRESS, 1)
        self.get_current_height()
        self.check_result("crc proposal tracking progress type", ret)
        Logger.info("{} crc proposal tracking progress on success!".format(
            self.tag))

        # Reject
        ret = self.crc_proposal_tracking(None, CRCProposalTracking.REJECTED, 2)
        self.get_current_height()
        self.check_result("crc proposal tracking reject type", ret)
        Logger.info("{} crc proposal tracking reject on success!".format(
            self.tag))

        # progress
        ret = self.crc_proposal_tracking(None, CRCProposalTracking.PROGRESS, 2)
        self.get_current_height()
        self.check_result("crc proposal tracking progress type", ret)
        Logger.info("{} crc proposal tracking progress on success!".format(
            self.tag))

        # proposal leader
        ela_node = self.node_manager.ela_nodes[2]
        new_leader_private_key = ela_node.cr_account.private_key()
        ret = self.crc_proposal_tracking(new_leader_private_key,
                                         CRCProposalTracking.PROPOSAL_LEADER,
                                         0)
        self.get_current_height()
        self.check_result("crc proposal tracking proposal leader type", ret)
        Logger.info(
            "{} crc proposal tracking proposal leader on success!".format(
                self.tag))
        self.owner_private_key = new_leader_private_key

        # finalized
        ret = self.crc_proposal_tracking(None, CRCProposalTracking.FINALIZED,
                                         3)
        self.get_current_height()
        self.check_result("crc proposal tracking finalized type", ret)
        Logger.info("{} crc proposal tracking finalized on success!".format(
            self.tag))

        # Terminated
        # ret = self.crc_proposal_tracking(p_hash, leader_private_key, None, CRCProposalTracking.TERMINATED, 0)
        # self.get_current_height()
        # self.check_result("crc proposal tracking terminated type", ret)
        # Logger.info("{} crc proposal tracking terminated on success!".format(self.tag))

    def ready_for_crc_proposal_withdraw(self):
        ret = self.crc_proposal_withdraw()
        self.get_current_height()
        self.check_result("crc proposal withdraw", ret)
        Logger.info("{} crc proposal withdraw on success!".format(self.tag))

    def crc_proposal_withdraw(self):
        global result
        result = True

        # Recipient
        ela_node = self.node_manager.ela_nodes[1]
        recipient = ela_node.cr_account.address()

        # leader privatekey
        ela_node = self.node_manager.ela_nodes[2]
        cr_private_key = ela_node.cr_account.private_key()

        withdraw = CRCProposalWithdraw(
            private_key=cr_private_key,
            proposal_hash=self.crc_proposal_hash,
        )
        Logger.info("{} create crc proposal withdraw on success. \n{}".format(
            self.tag, withdraw))

        amount = self.get_withdraw_amount(
            util.bytes_reverse(self.crc_proposal_hash).hex()) - util.TX_FEE
        ret = self.tx_manager.crc_proposal_withdraw(
            input_address=self.CRC_COMMITTEE_ADDRESS,
            amount=amount,
            crc_proposal_withdraw=withdraw,
            output_address=recipient)
        if not ret:
            return False
        self.discrete_miner(1)
        return result

    def crc_proposal_review(self):
        global result
        result = True
        for i in range(1, self.params.ela_params.crc_number + 1):
            ela_node = self.node_manager.ela_nodes[i]
            cr_private_key = ela_node.cr_account.private_key()
            review = CRCProposalReview(private_key=cr_private_key,
                                       proposal_hash=self.crc_proposal_hash,
                                       vote_result=CRCProposalReview.APPROVE,
                                       opinion_hash=Random.get_random_bytes(
                                           serialize.UINT256SIZE))
            Logger.info(
                "{} create crc proposal review on success. \n{}".format(
                    self.tag, review))
            ret = self.tx_manager.crc_proposal_review(
                input_private_key=self.tap_account.private_key(),
                amount=10 * constant.TO_SELA,
                crc_proposal_review=review)
            if not ret:
                return False
            self.discrete_miner(1)
            Logger.info("{} node-{} review on success!\n".format(self.tag, i))
        return result

    def crc_proposal_tracking(self, new_leader_private_key, tracking_type: int,
                              stage: int):
        global result
        result = True
        tracking = CRCProposalTracking(
            secretary_private_key=self.secretary_private_key,
            leader_private_key=self.owner_private_key,
            new_leader_private_key=new_leader_private_key,
            proposal_hash=self.crc_proposal_hash,
            document_hash=Random.get_random_bytes(serialize.UINT256SIZE),
            stage=stage,
            tracking_type=tracking_type,
            secretary_opinion_hash=Random.get_random_bytes(
                serialize.UINT256SIZE),
        )
        Logger.info("{} create crc proposal tracking on success. \n{}".format(
            self.tag, tracking))
        ret = self.tx_manager.crc_proposal_tracking(
            input_private_key=self.tap_account.private_key(),
            amount=10 * constant.TO_SELA,
            crc_proposal_tracking=tracking)
        if not ret:
            return False
        self.discrete_miner(1)
        return result

    def crc_proposal_secretary_general(self):
        ela_node = self.node_manager.ela_nodes[1]
        cr_private_key = ela_node.cr_account.private_key()
        ela_node = self.node_manager.ela_nodes[2]
        secretary_general_private_key = ela_node.cr_account.private_key()

        result = True
        crc_proposal = CRCProposal(
            private_key=cr_private_key,
            cr_private_key=cr_private_key,
            secretary_general_private_key=secretary_general_private_key,
            proposal_type=CRCProposal.SECRETARY_GENERAL,
            category_data="",
            draft_hash=Random.get_random_bytes(serialize.UINT256SIZE))
        Logger.info(
            "{} create crc proposal change secretary general on success. \n{}".
            format(self.tag, crc_proposal))

        ret = self.tx_manager.crc_proposal(
            input_private_key=self.tap_account.private_key(),
            amount=10 * constant.TO_SELA,
            crc_proposal=crc_proposal)
        if not ret:
            return False
        self.discrete_miner(1)
        return result

    def crc_proposal_change_owner(self):
        ela_node = self.node_manager.ela_nodes[1]
        cr_private_key = ela_node.cr_account.private_key()
        ela_node = self.node_manager.ela_nodes[2]
        new_owner_private_key = ela_node.cr_account.private_key()
        result = True
        crc_proposal = CRCProposal(
            private_key=cr_private_key,
            cr_private_key=cr_private_key,
            new_owner_private_key=new_owner_private_key,
            proposal_type=CRCProposal.CHANGE_SPONSOR_OWNER,
            category_data="",
            draft_hash=Random.get_random_bytes(serialize.UINT256SIZE),
            target_proposal_hash=self.crc_proposal_hash)
        Logger.info(
            "{} create crc proposal change owner on success. \n{}".format(
                self.tag, crc_proposal))

        ret = self.tx_manager.crc_proposal(
            input_private_key=self.tap_account.private_key(),
            amount=10 * constant.TO_SELA,
            crc_proposal=crc_proposal)
        if not ret:
            return False
        self.discrete_miner(1)
        return result

    def crc_proposal(self):
        ela_node = self.node_manager.ela_nodes[1]
        cr_private_key = ela_node.cr_account.private_key()
        self.owner_private_key = cr_private_key
        budget_list = list()
        budget_list.append(
            Budget(budget_type=Budget.IMPREST, stage=0, amount=100000))
        budget_list.append(
            Budget(budget_type=Budget.NORMAL_PAYMENT, stage=1, amount=200000))
        budget_list.append(
            Budget(budget_type=Budget.NORMAL_PAYMENT, stage=2, amount=300000))
        budget_list.append(
            Budget(budget_type=Budget.FINAL_PAYMENT, stage=3, amount=400000))
        result = True
        crc_proposal = CRCProposal(
            private_key=cr_private_key,
            cr_private_key=cr_private_key,
            proposal_type=CRCProposal.NORMAL,
            category_data="",
            draft_hash=Random.get_random_bytes(serialize.UINT256SIZE),
            budget=budget_list,
            recipient=bytes.fromhex(ela_node.cr_account.program_hash()))
        Logger.info("{} create crc proposal on success. \n{}".format(
            self.tag, crc_proposal))

        ret = self.tx_manager.crc_proposal(
            input_private_key=self.tap_account.private_key(),
            amount=10 * constant.TO_SELA,
            crc_proposal=crc_proposal)
        self.crc_proposal_hash = crc_proposal.hash
        if not ret:
            return False
        self.discrete_miner(1)
        return result

    def register_cr_candidates(self):

        global result
        result = True
        for i in range(1, self.params.ela_params.crc_number + 1):
            ela_node = self.node_manager.ela_nodes[i]
            cid = ela_node.cr_account.cid_address()
            cr_info = self.create_cr_info(
                register_private_key=ela_node.cr_account.private_key(),
                nickname="CR-00{}".format(i),
                url="www.00{}.com".format(i),
                location=0)
            ret = self.tx_manager.register_cr(
                input_private_key=self.tap_account.private_key(),
                amount=5000 * constant.TO_SELA,
                cr_info=cr_info)
            if not ret:
                return False
            self.discrete_miner(7)
            status = self.get_cr_status(cid)
            Logger.debug(
                "After mining 7 blocks, register status: {}".format(status))
            result = status == "Active"
            if not result:
                Logger.error("{} register CR {} failed".format(
                    self.tag, ela_node.name))
                break
            Logger.info("{} register CR-{} to be a CR on success!\n".format(
                self.tag, i))

        return result

    def create_cr_info(self, register_private_key: str, nickname: str,
                       url: str, location: int):
        cr_info = CRInfo(private_key=register_private_key,
                         nickname=nickname,
                         url=url,
                         location=location)
        Logger.info("{} create cr_info on success. \n{}".format(
            self.tag, cr_info))
        return cr_info

    def register_a_cr(self, input_private_key: str, cr_info: CRInfo):
        ret = self.tx_manager.register_cr(input_private_key=input_private_key,
                                          amount=5000 * constant.TO_SELA,
                                          cr_info=cr_info)

        self.check_result("register a cr", ret)

        return ret

    def create_crc_proposal(self, register_private_key: str, nickname: str,
                            url: str, location: int):
        cr_info = CRInfo(private_key=register_private_key,
                         nickname=nickname,
                         url=url,
                         location=location)
        Logger.info("{} create create_crc_proposal on success. \n{}".format(
            self.tag, cr_info))
        return cr_info

    def create_crc_proposal_review(self, register_private_key: str,
                                   nickname: str, url: str, location: int):
        cr_info = CRInfo(private_key=register_private_key,
                         nickname=nickname,
                         url=url,
                         location=location)
        Logger.info(
            "{} create create_crc_proposal_review on success. \n{}".format(
                self.tag, cr_info))
        return cr_info

    def create_crc_tracking(self, register_private_key: str, nickname: str,
                            url: str, location: int):
        cr_info = CRInfo(private_key=register_private_key,
                         nickname=nickname,
                         url=url,
                         location=location)
        Logger.info("{} create create_crc_tracking on success. \n{}".format(
            self.tag, cr_info))
        return cr_info

    def mining_blocks_ready(self, foundation_address):
        time.sleep(3)
        rpc.discrete_mining(110)
        balance = rpc.get_balance_by_address(foundation_address)
        Logger.debug("{} foundation address value: {}".format(
            self.tag, balance))

    def check_params(self):
        if self.params.ela_params.number < 3 * self.params.ela_params.crc_number + \
                self.params.ela_params.later_start_number:
            Logger.error(
                "Ela node number should be >= 3 * crc number + later start number , "
                "please check your config in the beginning of your test case or config.json, exit..."
            )
            time.sleep(1)
            exit(-1)

    def get_arbiter_names(self, category: str):
        arbiters = rpc.get_arbiters_info()[category]
        current_nicknames = list()
        for public_key in arbiters:
            current_nicknames.append(
                self.node_manager.node_pubkey_name_dict[public_key])

        return current_nicknames

    def show_arbiter_info(self):
        arbiters_nicknames = self.get_arbiter_names("arbiters")
        arbiters_nicknames.sort()
        next_arbiter_nicknames = self.get_arbiter_names("nextarbiters")
        next_arbiter_nicknames.sort()
        Logger.info(
            "current arbiters nicknames: {}".format(arbiters_nicknames))
        Logger.info(
            "next    arbiters nicknames: {}".format(next_arbiter_nicknames))

    def reset_config(self, up_config: dict):
        for key in up_config.keys():
            if key is "side":
                if not up_config[key]:
                    self.config["arbiter"]["enable"] = False
                    self.config["did"]["enable"] = False
                    self.config["token"]["enable"] = False
                    self.config["neo"]["enable"] = False
                continue

            if key in self.node_types:
                _config = self.up_config[key]
                for k in _config.keys():
                    self.config[key][k] = _config[k]

    def terminate_all_process(self, result=True):
        Logger.info("{} terminal all the process and exit...".format(self.tag))
        self.node_manager.stop_nodes()
        time.sleep(1)
        os.system("sh {}/shell/killall.sh".format(self.root_path))
        if result:
            exit(0)

    def start_later_nodes(self):
        for node in self.later_nodes:
            node.start()

    def check_result(self, case: str, result: bool):
Esempio n. 11
0
class TxControl(object):
    PRODUCER_STATE_ACTIVE = "Active"
    PRODUCER_STATE_INACTIVE = "Inactive"

    # CR_Foundation_TEMP = "EULhetag9FKS6Jd6aifFaPqjFTpZbSMY7u"
    CR_Foundation_TEMP = "CRASSETSXXXXXXXXXXXXXXXXXXXX2qDX5J"
    SECRETARY_PRIVATE_KEY = "E0076A271A137A2BD4429FA46E79BE3E10F2A730585F8AC2763D570B60469F11"
    CRC_COMMITTEE_ADDRESS = "CREXPENSESXXXXXXXXXXXXXXXXXX4UdT6b"

    def __init__(self, config: dict):
        self.tag = util.tag_from_path(__file__, TxControl.__name__)
        self._init_config(config)
        self.tap_account = Account(private_key_str=self.tap_private_key)
        self.pressure_account = Account(
            private_key_str=self.pressure_private_key)
        self.register_amount = 6000
        self.node_amount = 5000
        self.dpos_votes_dict = dict()
        self.producers_list = list()
        self.cr_list = list()
        self.tx_manager = TxManager(self.rpc_port)

    def _init_config(self, config: dict):
        self.rpc_port = config["rpc_port"]
        self.host = config["host"]
        self.outputs_num = config["outputs_num"]
        self.inputs_num = config["inputs_num"]
        self.block_size = config["block_size"]
        self.pressure_private_key = config["pressure_private_key"]
        self.tap_private_key = config["tap_private_key"]
        self.lock_address = config["lock_address"]
        self.recharge = config["recharge"]
        self.eth_tap_address = config["eth_tap_address"]
        rpc.DEFAULT_HOST = self.host

    def ready_for_pressure_outputs(self):
        ret = self.pressure_outputs()
        self.check_result(
            "pressure outputs number:{}".format(self.outputs_num), ret)
        Logger.info("{}pressure outputs on success!".format(self.tag))

    def ready_for_pressure_inputs(self):
        ret = self.pressure_inputs()
        self.check_result("pressure inputs number:{}".format(self.inputs_num),
                          ret)
        Logger.info("{}pressure inputs on success!".format(self.tag))

    def ready_for_pressure_cross_chain(self):
        Logger.info("waiting for cross chain pressure test ... ")
        ret = self.pressure_cross_chain()
        self.check_result(
            "pressure cross chain number:{}".format(self.outputs_num), ret)
        Logger.info("{}pressure cross chain on success!".format(self.tag))

    def ready_for_pressure_big_block(self):
        ret = self.pressure_big_block()
        self.check_result(
            "pressure big block size:{} ".format(self.block_size), ret)
        Logger.info("{}pressure big block on success!".format(
            self.tag, self.block_size))

    def pressure_outputs(self):
        output_addresses = list()
        for i in range(self.outputs_num):
            output_addresses.append(self.pressure_account.address())
        ret = self.tx_manager.transfer_asset(self.tap_account.private_key(),
                                             output_addresses,
                                             util.TX_SINGLE_OUTPUT,
                                             not self.recharge)
        if ret:
            self.wait_block()
            return True
        else:
            Logger.error("{} pressure outputs transfer failed".format(
                self.tag))
            return False

    def pressure_inputs(self):

        value = self.inputs_num * util.TX_FEE
        Logger.debug("{} account {} wallet balance: {}".format(
            self.tag, self.pressure_account.address(), value))

        ret = self.tx_manager.transfer_asset(
            self.pressure_account.private_key(), [self.tap_account.address()],
            value - util.TX_FEE)
        if ret:
            self.wait_block()
            return True
        else:
            Logger.error("{} pressure inputs transfer failed".format(self.tag))
            return False

    def pressure_cross_chain(self):

        value = self.outputs_num * util.TX_SINGLE_OUTPUT
        Logger.info("{} account {} wallet balance: {}".format(
            self.tag, self.pressure_account.address(), value))

        #self.tap_account.address(),
        #"0x53781e106a2e3378083bdcede1874e5c2a7225f8",
        ret = self.tx_manager.transfer_multi_cross_chain_asset(
            self.pressure_account.private_key(), self.lock_address,
            self.eth_tap_address, self.outputs_num,
            util.TX_SINGLE_OUTPUT - util.TX_FEE, self.recharge, self.rpc_port)
        if ret:
            self.wait_block()
            return True
        else:
            Logger.error("{} pressure inputs transfer failed".format(self.tag))
            return False

    def pressure_big_block(self):
        attributes = list()
        attribute = Attribute(usage=Attribute.NONCE,
                              data=Random.get_random_bytes(self.block_size))
        attributes.append(attribute)
        ret = self.tx_manager.transfer_abnormal_asset(
            self.tap_account.private_key(), [self.tap_account.address()],
            1 * util.TO_SELA,
            attributes=attributes)
        if ret:
            self.wait_block()
            return True
        else:
            Logger.error("{} pressure big block transfer failed".format(
                self.tag))
            return False

    def ready_for_dpos(self):
        producers = rpc.list_producers(0, 100, state="active")
        if producers is None:
            Logger.info('{} list producers is null'.format(self.tag))
            return
        Logger.debug('{} list producers:{}'.format(self.tag, producers))
        self.producers_list = producers["producers"]
        ret = self.vote_producers_candidates()
        self.check_result("vote producers", ret)
        Logger.info("{} vote producer on success!".format(self.tag))
        # self.get_dpos_votes()

    def ready_for_cr(self):
        cr = rpc.list_current_crs()
        # cr = rpc.list_cr_candidates(0, 100, state="active")
        if cr is None:
            Logger.info('{} list cr is null'.format(self.tag))
            return
        Logger.debug('{} list cr:{}'.format(self.tag, cr))
        # self.cr_list = cr["crcandidatesinfo"]
        self.cr_list = cr["crmembersinfo"]
        ret = self.vote_cr_candidates()
        self.check_result("vote cr", ret)
        Logger.info("{} vote cr on success!".format(self.tag))

    def ready_for_crc_proposal(self):
        ret, p_hash = self.crc_proposal()
        self.get_current_height()
        self.check_result("crc proposal", ret)
        Logger.info("{} crc proposal on success!".format(self.tag))
        return p_hash

    def ready_for_crc_proposal_review(self, p_hash: bytes):
        ret = self.crc_proposal_review(p_hash)
        self.get_current_height()
        self.check_result("crc proposal review", ret)
        Logger.info("{} crc proposal review on success!".format(self.tag))
        self.discrete_miner(self.params.ela_params.proposal_cr_voting_period)

        ret = self.tx_manager.vote_crc_proposal_candidates()
        self.get_current_height()
        self.check_result("vote cr proposal", ret)
        Logger.info("{} vote crc proposal  on success!".format(self.tag))
        self.discrete_miner(
            self.params.ela_params.proposal_public_voting_period)

    def ready_for_crc_proposal_tracking(self, p_hash: bytes):
        ela_node = self.node_manager.ela_nodes[1]
        leader_private_key = ela_node.cr_account.private_key()
        # common
        ret = self.crc_proposal_tracking(p_hash, leader_private_key, None,
                                         CRCProposalTracking.COMMON, 0)
        self.get_current_height()
        self.check_result("crc proposal tracking common type", ret)
        Logger.info("{} crc proposal tracking common on success!".format(
            self.tag))

        # progress
        ret = self.crc_proposal_tracking(p_hash, leader_private_key, None,
                                         CRCProposalTracking.PROGRESS, 1)
        self.get_current_height()
        self.check_result("crc proposal tracking progress type", ret)
        Logger.info("{} crc proposal tracking progress on success!".format(
            self.tag))

        # Reject
        ret = self.crc_proposal_tracking(p_hash, leader_private_key, None,
                                         CRCProposalTracking.REJECTED, 2)
        self.get_current_height()
        self.check_result("crc proposal tracking reject type", ret)
        Logger.info("{} crc proposal tracking reject on success!".format(
            self.tag))

        # progress
        ret = self.crc_proposal_tracking(p_hash, leader_private_key, None,
                                         CRCProposalTracking.PROGRESS, 2)
        self.get_current_height()
        self.check_result("crc proposal tracking progress type", ret)
        Logger.info("{} crc proposal tracking progress on success!".format(
            self.tag))

        # proposal leader
        ela_node = self.node_manager.ela_nodes[2]
        new_leader_private_key = ela_node.cr_account.private_key()
        ret = self.crc_proposal_tracking(p_hash, leader_private_key,
                                         new_leader_private_key,
                                         CRCProposalTracking.PROPOSAL_LEADER,
                                         0)
        self.get_current_height()
        self.check_result("crc proposal tracking proposal leader type", ret)
        Logger.info(
            "{} crc proposal tracking proposal leader on success!".format(
                self.tag))

        # finalized
        ret = self.crc_proposal_tracking(p_hash, new_leader_private_key, None,
                                         CRCProposalTracking.FINALIZED, 3)
        self.get_current_height()
        self.check_result("crc proposal tracking finalized type", ret)
        Logger.info("{} crc proposal tracking finalized on success!".format(
            self.tag))

        # Terminated
        # ret = self.crc_proposal_tracking(p_hash, leader_private_key, None, CRCProposalTracking.TERMINATED, 0)
        # self.get_current_height()
        # self.check_result("crc proposal tracking terminated type", ret)
        # Logger.info("{} crc proposal tracking terminated on success!".format(self.tag))

    def ready_for_crc_proposal_withdraw(self, p_hash: bytes):
        ret = self.crc_proposal_withdraw(p_hash)
        self.get_current_height()
        self.check_result("crc proposal withdraw", ret)
        Logger.info("{} crc proposal withdraw on success!".format(self.tag))

    def crc_proposal_withdraw(self, p_hash: bytes):
        global result
        result = True

        # Recipient
        ela_node = self.node_manager.ela_nodes[1]
        recipient = ela_node.cr_account.address()

        # leader privatekey
        ela_node = self.node_manager.ela_nodes[2]
        cr_private_key = ela_node.cr_account.private_key()

        withdraw = CRCProposalWithdraw(
            private_key=cr_private_key,
            proposal_hash=p_hash,
        )
        Logger.info("{} create crc proposal withdraw on success. \n{}".format(
            self.tag, withdraw))

        amount = self.get_withdraw_amount(p_hash.hex()) - util.TX_FEE
        ret = self.tx_manager.crc_proposal_withdraw(
            input_address=self.CRC_COMMITTEE_ADDRESS,
            amount=amount,
            crc_proposal_withdraw=withdraw,
            output_address=recipient)
        if not ret:
            return False
        self.discrete_miner(1)
        return result

    def crc_proposal_review(self, p_hash: bytes):
        global result
        result = True
        for i in range(1, self.params.ela_params.crc_number + 1):
            ela_node = self.node_manager.ela_nodes[i]
            cr_private_key = ela_node.cr_account.private_key()
            review = CRCProposalReview(private_key=cr_private_key,
                                       proposal_hash=p_hash,
                                       vote_result=CRCProposalReview.APPROVE,
                                       opinion_hash=Random.get_random_bytes(
                                           serialize.UINT256SIZE))
            Logger.info(
                "{} create crc proposal review on success. \n{}".format(
                    self.tag, review))
            ret = self.tx_manager.crc_proposal_review(
                input_private_key=self.tap_account.private_key(),
                amount=10 * constant.TO_SELA,
                crc_proposal_review=review)
            if not ret:
                return False
            self.discrete_miner(1)
            Logger.info("{} node-{} review on success!\n".format(self.tag, i))
        return result

    def crc_proposal_tracking(self, p_hash: bytes, leader_private_key: str,
                              new_leader_private_key, tracking_type: int,
                              stage: int):
        global result
        result = True
        tracking = CRCProposalTracking(
            secretary_private_key=self.SECRETARY_PRIVATE_KEY,
            leader_private_key=leader_private_key,
            new_leader_private_key=new_leader_private_key,
            proposal_hash=p_hash,
            document_hash=Random.get_random_bytes(serialize.UINT256SIZE),
            stage=stage,
            tracking_type=tracking_type,
            secretary_opinion_hash=Random.get_random_bytes(
                serialize.UINT256SIZE),
        )
        Logger.info("{} create crc proposal tracking on success. \n{}".format(
            self.tag, tracking))
        ret = self.tx_manager.crc_proposal_tracking(
            input_private_key=self.tap_account.private_key(),
            amount=10 * constant.TO_SELA,
            crc_proposal_tracking=tracking)
        if not ret:
            return False
        self.discrete_miner(1)
        return result

    def crc_proposal(self):
        ela_node = self.node_manager.ela_nodes[1]
        cr_private_key = ela_node.cr_account.private_key()
        budget_list = list()
        budget_list.append(
            Budget(budget_type=Budget.IMPREST, stage=0, amount=100000))
        budget_list.append(
            Budget(budget_type=Budget.NORMAL_PAYMENT, stage=1, amount=200000))
        budget_list.append(
            Budget(budget_type=Budget.NORMAL_PAYMENT, stage=2, amount=300000))
        budget_list.append(
            Budget(budget_type=Budget.FINAL_PAYMENT, stage=3, amount=400000))
        result = True
        crc_proposal = CRCProposal(
            private_key=cr_private_key,
            cr_private_key=cr_private_key,
            proposal_type=CRCProposal.NORMAL,
            category_data="normal",
            draft_hash=Random.get_random_bytes(serialize.UINT256SIZE),
            budget=budget_list,
            recipient=bytes.fromhex(ela_node.cr_account.program_hash()))
        Logger.info("{} create crc proposal on success. \n{}".format(
            self.tag, crc_proposal))

        ret = self.tx_manager.crc_proposal(
            input_private_key=self.tap_account.private_key(),
            amount=10 * constant.TO_SELA,
            crc_proposal=crc_proposal)
        if not ret:
            return False, crc_proposal.hash
        self.discrete_miner(1)
        return result, crc_proposal.hash

    def register_cr_candidates(self):

        global result
        result = True
        for i in range(1, self.params.ela_params.crc_number + 1):
            ela_node = self.node_manager.ela_nodes[i]
            cid = ela_node.cr_account.cid_address()
            cr_info = self.create_cr_info(
                register_private_key=ela_node.cr_account.private_key(),
                nickname="CR-00{}".format(i),
                url="www.00{}.com".format(i),
                location=0)
            ret = self.tx_manager.register_cr(
                input_private_key=self.tap_account.private_key(),
                amount=5000 * constant.TO_SELA,
                cr_info=cr_info)
            if not ret:
                return False
            self.discrete_miner(7)
            status = self.get_cr_status(cid)
            Logger.debug(
                "After mining 7 blocks, register status: {}".format(status))
            result = status == "Active"
            if not result:
                Logger.error("{} register CR {} failed".format(
                    self.tag, ela_node.name))
                break
            Logger.info("{} register node-{} to be a CR on success!\n".format(
                self.tag, i))

        return result

    def create_cr_info(self, register_private_key: str, nickname: str,
                       url: str, location: int):
        cr_info = CRInfo(private_key=register_private_key,
                         nickname=nickname,
                         url=url,
                         location=location)
        Logger.info("{} create cr_info on success. \n{}".format(
            self.tag, cr_info))
        return cr_info

    def register_a_cr(self, input_private_key: str, cr_info: CRInfo):
        ret = self.tx_manager.register_cr(input_private_key=input_private_key,
                                          amount=5000 * constant.TO_SELA,
                                          cr_info=cr_info)

        self.check_result("register a cr", ret)

        return ret

    def create_crc_proposal(self, register_private_key: str, nickname: str,
                            url: str, location: int):
        cr_info = CRInfo(private_key=register_private_key,
                         nickname=nickname,
                         url=url,
                         location=location)
        Logger.info("{} create create_crc_proposal on success. \n{}".format(
            self.tag, cr_info))
        return cr_info

    def create_crc_proposal_review(self, register_private_key: str,
                                   nickname: str, url: str, location: int):
        cr_info = CRInfo(private_key=register_private_key,
                         nickname=nickname,
                         url=url,
                         location=location)
        Logger.info(
            "{} create create_crc_proposal_review on success. \n{}".format(
                self.tag, cr_info))
        return cr_info

    def create_crc_tracking(self, register_private_key: str, nickname: str,
                            url: str, location: int):
        cr_info = CRInfo(private_key=register_private_key,
                         nickname=nickname,
                         url=url,
                         location=location)
        Logger.info("{} create create_crc_tracking on success. \n{}".format(
            self.tag, cr_info))
        return cr_info

    def mining_blocks_ready(self, foundation_address):
        time.sleep(3)
        rpc.discrete_mining(110)
        balance = rpc.get_balance_by_address(foundation_address)
        Logger.debug("{} foundation address value: {}".format(
            self.tag, balance))

    def check_params(self):
        if self.params.ela_params.number < 3 * self.params.ela_params.crc_number + \
                self.params.ela_params.later_start_number:
            Logger.error(
                "Ela node number should be >= 3 * crc number + later start number , "
                "please check your config in the beginning of your test case or config.json, exit..."
            )
            time.sleep(1)
            exit(-1)

    def get_arbiter_names(self, category: str):
        arbiters = rpc.get_arbiters_info()[category]
        current_nicknames = list()
        for public_key in arbiters:
            current_nicknames.append(
                self.node_manager.node_pubkey_name_dict[public_key])

        return current_nicknames

    def show_arbiter_info(self):
        arbiters_nicknames = self.get_arbiter_names("arbiters")
        arbiters_nicknames.sort()
        next_arbiter_nicknames = self.get_arbiter_names("nextarbiters")
        next_arbiter_nicknames.sort()
        Logger.info(
            "current arbiters nicknames: {}".format(arbiters_nicknames))
        Logger.info(
            "next    arbiters nicknames: {}".format(next_arbiter_nicknames))

    def reset_config(self, up_config: dict):
        for key in up_config.keys():
            if key is "side":
                if not up_config[key]:
                    self.config["arbiter"]["enable"] = False
                    self.config["did"]["enable"] = False
                    self.config["token"]["enable"] = False
                    self.config["neo"]["enable"] = False
                continue

            if key in self.node_types:
                _config = self.up_config[key]
                for k in _config.keys():
                    self.config[key][k] = _config[k]

    def vote_producers_candidates(self):
        candidates = list()
        vote_amount = 10
        p = len(self.producers_list)
        if len(self.producers_list) > 36:
            p = 36
        for i in range(1, p):
            producer = self.producers_list[i]["ownerpublickey"]
            candidates.append(
                CandidateVotes(bytes.fromhex(producer), vote_amount))
        ret = self.tx_manager.vote_producer(
            input_private_key=self.tap_private_key,
            amount=vote_amount,
            candidates=candidates,
        )
        if not ret:
            return False
        self.wait_block()
        return True

    def vote_cr_candidates(self):
        candidates = list()
        amount = 0
        p = len(self.cr_list)
        if len(self.cr_list) > 36:
            p = 36
        for i in range(1, p):
            cr = self.cr_list[i]["cid"]
            vote_amount = i * 10
            amount += vote_amount
            candidates.append(
                CandidateVotes(keytool.address_to_program_hash(cr),
                               vote_amount))
        ret = self.tx_manager.vote_cr(
            input_private_key=self.tap_account.private_key(),
            amount=amount,
            candidates=candidates,
        )
        if not ret:
            return False
        self.wait_block()
        return True

    def check_result(self, case: str, result: bool):