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 __init__(self, register_private_key: str): Payload.__init__(self, self.DEFAULT_VERSION) self.account = Account(register_private_key) self.cid = self.account.cid() self.signature = None self.gen_signature() self.serialize_data = None
def __init__(self, private_key: str, cr_private_key: str, proposal_type: int, category_data: str, draft_hash: bytes, budget=None, recipient=None, target_proposal_hash=None, new_recipient=None, secretary_general_private_key=None, new_owner_private_key=None): Payload.__init__(self, self.DEFAULT_VERSION) self.account = Account(private_key) self.cr_account = Account(cr_private_key) self.secretary_general_account = None self.new_owner_account = None self.proposal_type = proposal_type self.category_data = category_data self.draft_hash = draft_hash self.target_proposal_hash = target_proposal_hash self.new_owner_public_key = None self.budget = budget self.recipient = recipient self.new_recipient = None self.secretary_general_public_key = None self.secretary_general_did = None self.sign = None self.new_owner_signature = None self.secretary_general_signature = None self._gen_secretary_general_account(secretary_general_private_key) self._gen_new_owner_account(new_owner_private_key) self.cr_council_member_did = bytes.fromhex(self.cr_account.did()) self.cr_council_member_sign = None self._gen_signature() self.hash = self.gen_hash() self.serialize_data = None
def __init__(self, private_key: str, proposal_hash: bytes): Payload.__init__(self, self.DEFAULT_VERSION) self.account = Account(private_key) self.proposal_hash = proposal_hash self.sponsor_public_key = bytes.fromhex(self.account.public_key()) self.sign = None self.gen_signature() self.serialize_data = None
def __init__(self, private_key: str, proposal_hash: bytes, vote_result: int, opinion_hash: bytes): Payload.__init__(self, self.DEFAULT_VERSION) self.account = Account(private_key) self.proposal_hash = proposal_hash self.vote_result = vote_result self.opinion_hash = opinion_hash self.did = bytes.fromhex(self.account.did()) self.sign = None self.gen_signature() self.serialize_data = None
class CRCProposalReview(Payload): APPROVE = 0x00 REJECT = 0x01 ABSTAIN = 0x02 def __init__(self, private_key: str, proposal_hash: bytes, vote_result: int, opinion_hash: bytes): Payload.__init__(self, self.DEFAULT_VERSION) self.account = Account(private_key) self.proposal_hash = proposal_hash self.vote_result = vote_result self.opinion_hash = opinion_hash self.did = bytes.fromhex(self.account.did()) self.sign = 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) r = serialize.write_var_bytes(r, self.sign) return r def serialize_unsigned(self, r: bytes, version=0): r += self.proposal_hash r += struct.pack("<B", self.vote_result) r += self.opinion_hash r += self.did return r def deserialize(self, r: bytes, version: int): pass def gen_signature(self): r = b"" r = self.serialize_unsigned(r, self.version) self.sign = keytool.ecdsa_sign(bytes.fromhex(self.account.private_key()), r) return r def __repr__(self): return "CRCProposalReview {" + "\n\t" \ + "privateKey: {}".format(self.account.private_key()) + "\n\t" \ + "proposalHash: {}".format(self.proposal_hash.hex()) + "\n\t" \ + "voteResult : {}".format(self.vote_result) + "\n\t" \ + "crOpinionHash: {}".format(self.opinion_hash.hex()) + "\n\t" \ + "did : {}".format(keytool.create_address(self.did)) + "\n\t" \ + "sign: {}".format(self.sign.hex()) + "\n\t" \ + "}"
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 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 __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 __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)
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 test_content(): test_case = "update producer after pre offset but before h2" controller = Controller(config) controller.ready_for_dpos() h1 = controller.params.ela_params.crc_dpos_height h2 = controller.params.ela_params.public_dpos_height pre_offset = config["ela"]["pre_connect_offset"] update_node_prikey = "aa8ad6d1ac6953f7b9a68b5b13fe79d7217fb687651c1c30be12e5e0328b667f" # update_producer_beforeh1 = controller.tx_manager.register_producers_list[0] update_producer = controller.tx_manager.register_producers_list[0] current_height = controller.get_current_height() if current_height < h1 - 5: controller.discrete_mining_blocks(h1 - 5 - current_height) height_times = dict() height_times[current_height] = 1 global result global update_height update_height = 0 while True: current_height = controller.get_current_height() times = controller.get_height_times(height_times, current_height) Logger.debug("current height: {}, times: {}".format( current_height, times)) if times >= 100: result = False break if current_height >= h1: controller.show_arbiter_info() if update_height == 0 and current_height > h1 + 35: producer_payload = update_producer.producer_info() producer_payload.nickname = "^_^ HAHA" producer_payload.node_account = Account(update_node_prikey) producer_payload.url = "127.0.0.1" result = controller.tx_manager.update_producer( update_producer, producer_payload) controller.check_result(test_case, result) if result: controller.node_manager.node_pubkey_name_dict[ update_node_prikey] = producer_payload.nickname update_height = current_height if current_height > h2 + 100: break controller.discrete_mining_blocks(1) time.sleep(1) controller.check_result(test_case, result) controller.terminate_all_process(result)
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
class CRCProposalWithdraw(Payload): def __init__(self, private_key: str, proposal_hash: bytes): Payload.__init__(self, self.DEFAULT_VERSION) self.account = Account(private_key) self.proposal_hash = proposal_hash self.sponsor_public_key = bytes.fromhex(self.account.public_key()) self.sign = 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) r = serialize.write_var_bytes(r, self.sign) return r def serialize_unsigned(self, r: bytes, version=0): r += self.proposal_hash r = serialize.write_var_bytes(r, self.sponsor_public_key) return r def deserialize(self, r: bytes, version: int): pass def gen_signature(self): r = b"" r = self.serialize_unsigned(r, self.version) self.sign = keytool.ecdsa_sign( bytes.fromhex(self.account.private_key()), r) return r def __repr__(self): return "CRCProposalWithdraw {" + "\n\t" \ + "proposalHash: {}".format(self.proposal_hash.hex()) + "\n\t" \ + "sponsorPublicKey : {}".format(self.sponsor_public_key.hex()) + "\n\t" \ + "sign: {}".format(self.sign.hex()) + "\n\t" \ + "}"
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 __init__(self, secretary_private_key: str, leader_private_key: str, new_leader_private_key, tracking_type: int, proposal_hash: bytes, document_hash: bytes, stage: int, secretary_opinion_hash: bytes): Payload.__init__(self, self.DEFAULT_VERSION) self.secretary_general_account = Account(secretary_private_key) self.leader_account = Account(leader_private_key) self.new_leader_account = None self.proposal_hash = proposal_hash self.document_hash = document_hash self.stage = stage self.leader_public_key = bytes.fromhex( self.leader_account.public_key()) self.new_leader_public_key = None self.proposal_tracking_type = tracking_type self.secretary_opinion_hash = secretary_opinion_hash self.secretary_general_sign = None self.leader_sign = None self.new_leader_sign = None self._get_new_leader_account(new_leader_private_key) self.gen_signature() self.serialize_data = None
class UnRegisterCR(Payload): def __init__(self, register_private_key: str): Payload.__init__(self, self.DEFAULT_VERSION) self.account = Account(register_private_key) self.cid = self.account.cid() self.signature = None self.gen_signature() self.serialize_data = None 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 def data(self, version: int): r = b"" if self.serialize_data is not None: return self.serialize_data r = self.serialize(r, self.version) self.serialize_data = r return r def serialize(self, r: bytes, version: int): r = self.serialize_unsigned(r, self.version) if self.signature is not None: r = serialize.write_var_bytes(r, self.signature) return r def serialize_unsigned(self, r: bytes, version: int): r += bytes.fromhex(self.cid) return r def deserialize(self, r: bytes, version: int): pass
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 _get_account(self, index): encrypt_private_key = self._accounts_data_list[index][ "PrivateKeyEncrypted"] if encrypt_private_key is None: Logger.error("encrypt private key is None") return None encrypt_private_key_bytes = bytes.fromhex(encrypt_private_key) if len(encrypt_private_key_bytes) != 96: Logger.error("encrypt private key length is not 96") return None private_key = keytool.aes_decrypt(encrypt_private_key_bytes, self._master_key, self._iv)[64:96] account = Account(private_key.hex()) return account
def _read_key_stores(self, category: str, num: int): dest_path = os.path.join(self.stables_path, category + ".json") if not os.path.exists(dest_path): Logger.error( "{} read key stores failed, dest path {} is not found, exit..." .format(self.tag, dest_path)) time.sleep(1) exit(-1) content_dict = util.read_config_file(dest_path) for i in range(num): private_key_str = content_dict[category + "_" + str(i)]["private_key"] a = Account(private_key_str) self.category_dict[category].append(a) Logger.debug("{} load {} keystore on success !".format( self.tag, category))
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 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):
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 CRCProposal(Payload): NORMAL = 0x0000 ELIP = 0x0100 FLOW_ELIP = 0x0101 INFO_ELIP = 0x0102 MAIN_CHAIN_UPGRADE_CODE = 0x0200 SIDE_CHAIN_UPGRADE_CODE = 0x0300 REGISTER_SIDE_CHAIN = 0x0301 SECRETARY_GENERAL = 0x0400 CHANGE_SPONSOR_OWNER = 0x0401 CLOSE_PROPOSAL = 0x0402 DAPP_CONSENSUS = 0x0500 WRONG = 0x4321 def __init__(self, private_key: str, cr_private_key: str, proposal_type: int, category_data: str, draft_hash: bytes, budget=None, recipient=None, target_proposal_hash=None, new_recipient=None, secretary_general_private_key=None, new_owner_private_key=None): Payload.__init__(self, self.DEFAULT_VERSION) self.account = Account(private_key) self.cr_account = Account(cr_private_key) self.secretary_general_account = None self.new_owner_account = None self.proposal_type = proposal_type self.category_data = category_data self.draft_hash = draft_hash self.target_proposal_hash = target_proposal_hash self.new_owner_public_key = None self.budget = budget self.recipient = recipient self.new_recipient = None self.secretary_general_public_key = None self.secretary_general_did = None self.sign = None self.new_owner_signature = None self.secretary_general_signature = None self._gen_secretary_general_account(secretary_general_private_key) self._gen_new_owner_account(new_owner_private_key) self.cr_council_member_did = bytes.fromhex(self.cr_account.did()) self.cr_council_member_sign = None self._gen_signature() self.hash = self.gen_hash() 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): if self.proposal_type is self.SECRETARY_GENERAL: return self.serialize_secretary_general(r, version) elif self.proposal_type is self.CHANGE_SPONSOR_OWNER: return self.serialize_change_proposal_owner(r, version) elif self.proposal_type is self.CLOSE_PROPOSAL: return self.serialize_close_proposal(r, version) else: return self.serialize_normal_or_elip(r, version) def serialize_normal_or_elip(self, r: bytes, version: int): r = self.serialize_unsigned_normal_or_elip(r, version) r = serialize.write_var_bytes(r, self.sign) r += self.cr_council_member_did r = serialize.write_var_bytes(r, self.cr_council_member_sign) return r def serialize_secretary_general(self, r: bytes, version: int): r = self.serialize_unsigned_secretary_genera(r, version) r = serialize.write_var_bytes(r, self.sign) r = serialize.write_var_bytes(r, self.secretary_general_signature) r += self.cr_council_member_did r = serialize.write_var_bytes(r, self.cr_council_member_sign) return r def serialize_change_proposal_owner(self, r: bytes, version: int): r = self.serialize_unsigned_change_proposal_owner(r, version) r = serialize.write_var_bytes(r, self.sign) r = serialize.write_var_bytes(r, self.new_owner_signature) r += self.cr_council_member_did r = serialize.write_var_bytes(r, self.cr_council_member_sign) return r def serialize_close_proposal(self, r: bytes, version: int): r = self.serialize_unsigned_close_proposal(r, version) r = serialize.write_var_bytes(r, self.sign) r += self.cr_council_member_did r = serialize.write_var_bytes(r, self.cr_council_member_sign) return r def serialize_unsigned_normal_or_elip(self, r: bytes, version=0): r += struct.pack("<H", self.proposal_type) r = serialize.write_var_bytes(r, bytes(self.category_data.encode())) r = serialize.write_var_bytes(r, bytes.fromhex(self.account.public_key())) r += self.draft_hash r += serialize.write_var_uint(len(self.budget)) for budget in self.budget: r += budget.serialize(version) r += self.recipient return r def serialize_unsigned_secretary_genera(self, r: bytes, version=0): r += struct.pack("<H", self.proposal_type) r = serialize.write_var_bytes(r, bytes(self.category_data.encode())) r = serialize.write_var_bytes(r, bytes.fromhex(self.account.public_key())) r += self.draft_hash r = serialize.write_var_bytes(r, self.secretary_general_public_key) r += self.secretary_general_did return r def serialize_unsigned_change_proposal_owner(self, r: bytes, version=0): r += struct.pack("<H", self.proposal_type) r = serialize.write_var_bytes(r, bytes(self.category_data.encode())) r = serialize.write_var_bytes(r, bytes.fromhex(self.account.public_key())) r += self.draft_hash r += self.target_proposal_hash r += self.new_recipient r = serialize.write_var_bytes(r, self.new_owner_public_key) return r def serialize_unsigned_close_proposal(self, r: bytes, version=0): r += struct.pack("<H", self.proposal_type) r = serialize.write_var_bytes(r, bytes(self.category_data.encode())) r = serialize.write_var_bytes(r, bytes.fromhex(self.account.public_key())) r += self.draft_hash r += self.target_proposal_hash return r def deserialize(self, r: bytes, version: int): pass def _gen_secretary_general_account(self, private_key): if private_key is not None: self.secretary_general_account = Account(private_key) self.secretary_general_public_key = bytes.fromhex(self.secretary_general_account.public_key()) self.secretary_general_did = bytes.fromhex(self.secretary_general_account.did()) def _gen_new_owner_account(self, private_key): if private_key is not None: self.new_owner_account = Account(private_key) self.new_owner_public_key = bytes.fromhex(self.new_owner_account.public_key()) self.new_recipient = bytes.fromhex(self.new_owner_account.did()) def get_deposit_address(self): return self.account.deposit_address() def _gen_signature(self): r = b"" if self.proposal_type is self.SECRETARY_GENERAL: r = self.serialize_unsigned_secretary_genera(r, self.version) self.sign = keytool.ecdsa_sign(bytes.fromhex(self.account.private_key()), r) self.secretary_general_signature = keytool.ecdsa_sign( bytes.fromhex(self.secretary_general_account.private_key()), r) r = serialize.write_var_bytes(r, self.sign) r = serialize.write_var_bytes(r, self.secretary_general_signature) r += self.cr_council_member_did self.cr_council_member_sign = keytool.ecdsa_sign(bytes.fromhex(self.cr_account.private_key()), r) return r elif self.proposal_type is self.CHANGE_SPONSOR_OWNER: r = self.serialize_unsigned_change_proposal_owner(r, self.version) self.sign = keytool.ecdsa_sign(bytes.fromhex(self.account.private_key()), r) self.new_owner_signature = keytool.ecdsa_sign(bytes.fromhex(self.new_owner_account.private_key()), r) r = serialize.write_var_bytes(r, self.sign) r = serialize.write_var_bytes(r, self.new_owner_signature) r += self.cr_council_member_did self.cr_council_member_sign = keytool.ecdsa_sign(bytes.fromhex(self.cr_account.private_key()), r) return r elif self.proposal_type is self.CLOSE_PROPOSAL: r = self.serialize_unsigned_close_proposal(r, self.version) self.sign = keytool.ecdsa_sign(bytes.fromhex(self.account.private_key()), r) r = serialize.write_var_bytes(r, self.sign) r += self.cr_council_member_did self.cr_council_member_sign = keytool.ecdsa_sign(bytes.fromhex(self.cr_account.private_key()), r) return r else: r = self.serialize_unsigned_normal_or_elip(r, self.version) self.sign = keytool.ecdsa_sign(bytes.fromhex(self.account.private_key()), r) r = serialize.write_var_bytes(r, self.sign) r += self.cr_council_member_did self.cr_council_member_sign = keytool.ecdsa_sign(bytes.fromhex(self.cr_account.private_key()), r) return r def gen_hash(self): r = b"" r = self.serialize(r, 0) return keytool.sha256_hash(r, 2) def __repr__(self): if self.proposal_type is self.SECRETARY_GENERAL: return "CRCProposalSecretaryGeneral {" + "\n\t" \ + "privateKey: {}".format(self.proposal_type) + "\n\t" \ + "crCouncilMemberDid: {}".format(self.proposal_type) + "\n\t" \ + "proposalType: {}".format(self.proposal_type) + "\n\t" \ + "categoryData : {}".format(self.category_data) + "\n\t" \ + "sponsorPublicKey : {}".format(self.account.public_key()) + "\n\t" \ + "draftHash: {}".format(self.draft_hash.hex()) + "\n\t" \ + "secretaryGeneralPublicKey: {}".format(self.secretary_general_public_key.hex()) + "\n\t" \ + "secretaryGeneralDid: {}".format(keytool.create_address(self.secretary_general_did)) + "\n\t" \ + "sign: {}".format(self.sign.hex()) + "\n\t" \ + "secretaryGeneralSignature: {}".format(self.secretary_general_signature.hex()) + "\n\t" \ + "crCouncilMemberDid: {}".format(keytool.create_address(self.cr_council_member_did)) + "\n\t" \ + "crCouncilMemberSign: {}".format(self.cr_council_member_sign.hex()) + "\n\t" \ + "hash: {}".format(self.hash.hex()) + "\n\t" \ + "}" elif self.proposal_type is self.CHANGE_SPONSOR_OWNER: return "CRCProposalChangeSponsor {" + "\n\t" \ + "proposalType: {}".format(self.proposal_type) + "\n\t" \ + "categoryData : {}".format(self.category_data) + "\n\t" \ + "sponsorPublicKey : {}".format(self.account.public_key()) + "\n\t" \ + "draftHash: {}".format(self.draft_hash.hex()) + "\n\t" \ + "targetProposalHash: {}".format(self.target_proposal_hash.hex()) + "\n\t" \ + "newRecipient: {}".format(keytool.create_address(self.new_recipient)) + "\n\t" \ + "newOwnerPublicKey: {}".format(self.new_owner_public_key.hex()) + "\n\t" \ + "sign: {}".format(self.sign.hex()) + "\n\t" \ + "crCouncilMemberDid: {}".format(keytool.create_address(self.cr_council_member_did)) + "\n\t" \ + "crCouncilMemberSign: {}".format(self.cr_council_member_sign.hex()) + "\n\t" \ + "hash: {}".format(self.hash.hex()) + "\n\t" \ + "}" elif self.proposal_type is self.CLOSE_PROPOSAL: return "CRCProposalCloseProposal {" + "\n\t" \ + "proposalType: {}".format(self.proposal_type) + "\n\t" \ + "categoryData : {}".format(self.category_data) + "\n\t" \ + "sponsorPublicKey : {}".format(self.account.public_key()) + "\n\t" \ + "draftHash: {}".format(self.draft_hash.hex()) + "\n\t" \ + "targetProposalHash: {}".format(self.target_proposal_hash.hex) + "\n\t" \ + "sign: {}".format(self.sign.hex()) + "\n\t" \ + "crCouncilMemberDid: {}".format(keytool.create_address(self.cr_council_member_did)) + "\n\t" \ + "crCouncilMemberSign: {}".format(self.cr_council_member_sign.hex()) + "\n\t" \ + "hash: {}".format(self.hash.hex()) + "\n\t" \ + "}" else: return "CRCProposal {" + "\n\t" \ + "proposalType: {}".format(self.proposal_type) + "\n\t" \ + "categoryData : {}".format(self.category_data) + "\n\t" \ + "sponsorPublicKey : {}".format(self.account.public_key()) + "\n\t" \ + "draftHash: {}".format(self.draft_hash.hex()) + "\n\t" \ + "budgets: {}".format(self.budget) + "\n\t" \ + "recipient: {}".format(keytool.create_address(self.recipient)) + "\n\t" \ + "sign: {}".format(self.sign.hex()) + "\n\t" \ + "crCouncilMemberDid: {}".format(keytool.create_address(self.cr_council_member_did)) + "\n\t" \ + "crCouncilMemberSign: {}".format(self.cr_council_member_sign.hex()) + "\n\t" \ + "hash: {}".format(self.hash.hex()) + "\n\t" \ + "}"
class CRCProposalTracking(Payload): COMMON = 0x00 PROGRESS = 0x01 REJECTED = 0x02 TERMINATED = 0x03 PROPOSAL_LEADER = 0x04 FINALIZED = 0x05 DEFAULT = 0x00 def __init__(self, secretary_private_key: str, leader_private_key: str, new_leader_private_key, tracking_type: int, proposal_hash: bytes, document_hash: bytes, stage: int, secretary_opinion_hash: bytes): Payload.__init__(self, self.DEFAULT_VERSION) self.secretary_general_account = Account(secretary_private_key) self.leader_account = Account(leader_private_key) self.new_leader_account = None self.proposal_hash = proposal_hash self.document_hash = document_hash self.stage = stage self.leader_public_key = bytes.fromhex( self.leader_account.public_key()) self.new_leader_public_key = None self.proposal_tracking_type = tracking_type self.secretary_opinion_hash = secretary_opinion_hash self.secretary_general_sign = None self.leader_sign = None self.new_leader_sign = None self._get_new_leader_account(new_leader_private_key) 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) r = serialize.write_var_bytes(r, self.leader_sign) if self.new_leader_sign is not None: r = serialize.write_var_bytes(r, self.new_leader_sign) else: r += struct.pack("<B", CRCProposalTracking.DEFAULT) r += struct.pack("<B", self.proposal_tracking_type) r += self.secretary_opinion_hash r = serialize.write_var_bytes(r, self.secretary_general_sign) return r def serialize_unsigned(self, r: bytes, version=0): r += self.proposal_hash r += self.document_hash r += serialize.write_var_uint(self.stage) r = serialize.write_var_bytes(r, self.leader_public_key) if self.new_leader_public_key is not None: r = serialize.write_var_bytes(r, self.new_leader_public_key) else: r += struct.pack("<B", CRCProposalTracking.DEFAULT) return r def deserialize(self, r: bytes, version: int): pass def gen_signature(self): r = b"" r = self.serialize_unsigned(r, self.version) self.leader_sign = keytool.ecdsa_sign( bytes.fromhex(self.leader_account.private_key()), r) r = serialize.write_var_bytes(r, self.leader_sign) if self.new_leader_account is not None: self.new_leader_sign = keytool.ecdsa_sign( bytes.fromhex(self.new_leader_account.private_key()), r) r = serialize.write_var_bytes(r, self.new_leader_sign) else: self.new_leader_sign = None r += struct.pack("<B", CRCProposalTracking.DEFAULT) r += struct.pack("<B", self.proposal_tracking_type) r += self.secretary_opinion_hash self.secretary_general_sign = keytool.ecdsa_sign( bytes.fromhex(self.secretary_general_account.private_key()), r) return r def _get_new_leader_account(self, new_leader_private_key): if new_leader_private_key is not None: self.new_leader_account = Account(new_leader_private_key) self.new_leader_public_key = bytes.fromhex( self.new_leader_account.public_key()) def __repr__(self): return "CRCProposalTracking {" + "\n\t" \ + "SecretaryGeneralPrivateKey: {}".format(self.secretary_general_account.private_key()) + "\n\t" \ + "proposalTrackingType: {}".format(self.proposal_tracking_type) + "\n\t" \ + "proposalHash: {}".format(self.proposal_hash.hex()) + "\n\t" \ + "documentHash : {}".format(self.document_hash) + "\n\t" \ + "stage : {}".format(self.stage) + "\n\t" \ + "leaderPublicKey: {}".format(self.leader_public_key.hex()) + "\n\t" \ + "newLeaderPublicKey: {}".format(self.new_leader_public_key) + "\n\t" \ + "leaderSign: {}".format(self.leader_sign.hex()) + "\n\t" \ + "newLeaderSign: {}".format(self.new_leader_sign) + "\n\t" \ + "secretaryOpinionHash: {}".format(self.secretary_opinion_hash) + "\n\t" \ + "secretaryGeneralSign: {}".format(self.secretary_general_sign.hex()) + "\n\t" \ + "}"
def _create_keystore(self, category: str, num: int): keystore_saved_dir = os.path.join(self.key_message_saved_dir, category) if not os.path.exists(keystore_saved_dir): os.makedirs(keystore_saved_dir) for i in range(num): if i == 0: first_time = True else: first_time = False if category == "arbiter": a = Account(self.node_accounts[i].private_key()) else: a = Account() Logger.debug("{} {}_{} private key: {}".format( self.tag, category, i, a.private_key())) k = Keystore(a, self.password) self.category_dict[category].append(a) if category == "arbiter": sub1 = Account() k.add_sub_account(sub1) self.sub1_accounts.append(sub1) util.save_to_json( sub1, "sub1_" + str(i), os.path.join(self.key_message_saved_dir, "sub1.json"), first_time) sub2 = Account() k.add_sub_account(sub2) self.sub2_accounts.append(sub2) util.save_to_json( sub2, "sub2_" + str(i), os.path.join(self.key_message_saved_dir, "sub2.json"), first_time) sub3 = Account() k.add_sub_account(sub3) self.sub3_accounts.append(sub3) util.save_to_json( sub3, "sub3_" + str(i), os.path.join(self.key_message_saved_dir, "sub3.json"), first_time) sub4 = Account() k.add_sub_account(sub4) self.sub3_accounts.append(sub4) util.save_to_json( sub4, "sub4_" + str(i), os.path.join(self.key_message_saved_dir, "sub4.json"), first_time) util.save_to_json( a, category + "_" + str(i), os.path.join(self.key_message_saved_dir, category + ".json"), first_time) util.save_to_dat( k.key_store_dict(), os.path.join(keystore_saved_dir, category + str(i) + ".dat")) Logger.debug("{} create {} keystores on success!".format( self.tag, category))
def _get_new_leader_account(self, new_leader_private_key): if new_leader_private_key is not None: self.new_leader_account = Account(new_leader_private_key) self.new_leader_public_key = bytes.fromhex( self.new_leader_account.public_key())
def _gen_new_owner_account(self, private_key): if private_key is not None: self.new_owner_account = Account(private_key) self.new_owner_public_key = bytes.fromhex(self.new_owner_account.public_key()) self.new_recipient = bytes.fromhex(self.new_owner_account.did())