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_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
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_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
class CRInfo(Payload):
    CR_INFO_VERSION = 0x00
    CR_INFO_DID_VERSION = 0x01

    def __init__(self, private_key: str, nickname: str, url: str,
                 location: int):
        Payload.__init__(self, self.DEFAULT_VERSION)
        self.account = Account(private_key)
        self.nickname = nickname
        self.url = url
        self.location = location
        self.code = self.account.redeem_script()
        self.cid = self.account.cid()
        self.did = self.account.did()
        self.signature = None
        self.gen_signature()
        self.serialize_data = None

    def data(self, version: int):
        if self.serialize_data is not None:
            return self.serialize_data
        r = b""
        r = self.serialize(r, self.version)
        self.serialize_data = r
        return r

    def serialize(self, r: bytes, version: int):
        r = self.serialize_unsigned(r, version)

        if self.signature is not None:
            r = serialize.write_var_bytes(r, self.signature)

        return r

    def serialize_unsigned(self, r: bytes, version=0):
        r = serialize.write_var_bytes(r, bytes.fromhex(self.code))
        r += bytes.fromhex(self.cid)
        r += bytes.fromhex(self.did)
        r = serialize.write_var_bytes(r, bytes(self.nickname.encode()))
        r = serialize.write_var_bytes(r, bytes(self.url.encode()))
        r += struct.pack("<Q", self.location)

        return r

    def deserialize(self, r: bytes, version: int):
        pass

    def get_deposit_address(self):
        return self.account.deposit_address()

    def gen_signature(self):
        r = b""
        r = self.serialize_unsigned(r, self.version)
        signature = keytool.ecdsa_sign(
            bytes.fromhex(self.account.private_key()), r)
        self.signature = signature
        return signature

    def __repr__(self):
        return "CRInfo {" + "\n\t" \
               + "privateKey: {}".format(self.account.private_key()) + "\n\t" \
               + "code: {}".format(self.code) + "\n\t" \
               + "cid : {}".format(keytool.create_address(bytes.fromhex(self.cid))) + "\n\t" \
               + "did : {}".format(keytool.create_address(bytes.fromhex(self.did))) + "\n\t" \
               + "nickname: {}".format(self.nickname) + "\n\t" \
               + "url: {}".format(self.url) + "\n\t" \
               + "location: {}".format(self.location) + "\n\t" \
               + "signature: {}".format(self.signature.hex()) + "\n" \
               + "}"