def test_NE_P2P_003(global_test_env): log.info("Static node configuration test") all_node = global_test_env.get_all_nodes() # stop node if global_test_env.running: global_test_env.stop_all() # modify config file config_data = LoadFile(global_test_env.cfg.config_json_tmp).get_data() config_data['node']['P2P']['MaxPeers'] = 50 config_data['node']['P2P']['NoDiscovery'] = True config_data['node']['P2P']["BootstrapNodes"] = [] with open(global_test_env.cfg.config_json_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(config_data, indent=4)) all_node = global_test_env.get_all_nodes() # upload config file global_test_env.executor(one_put_config_task, all_node) # start node global_test_env.cfg.init_chain = False global_test_env.start_all() # run ssh static_number = len(global_test_env.get_static_nodes()) for node in all_node: # cmd_list = run_ssh_cmd(node.ssh, "netstat -an | grep 16789 | grep ESTABLISHED |wc -l") # log.info(node.web3.net.peerCount) # assert int(cmd_list[0][0]) <= static_number assert node.web3.net.peerCount <= static_number
def test_NE_P2P_001(global_test_env): log.info("Node maximum link quantity test") all_node = global_test_env.get_all_nodes() # stop node if global_test_env.running: global_test_env.stop_all() # modify config file config_data = LoadFile(global_test_env.cfg.config_json_tmp).get_data() config_data['node']['P2P']['MaxPeers'] = 2 with open(global_test_env.cfg.config_json_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(config_data, indent=4)) # upload config file global_test_env.executor(one_put_config_task, all_node) # start node global_test_env.cfg.init_chain = False global_test_env.start_all() # run ssh static_number = len(global_test_env.get_static_nodes()) for node in all_node: cmd_list = run_ssh_cmd(node.ssh, "netstat -an | grep 16789 | grep ESTABLISHED |wc -l") assert int(cmd_list[0][0]) <= 2 + static_number
def update_config(self, key1, key2, key3=None, value=None, file=conf.PLATON_CONFIG_PATH): ''' 修改config配置参数 :param key1: 第一层级key :param key2: 第二层级key :param key3: 第三层级key :param value: :param file: :return: ''' data = LoadFile(file).get_data() if key3 == None: data[key1][key2] = value else: data[key1][key2][key3] = value data = json.dumps(data) with open(conf.PLATON_CONFIG_PATH, "w") as f: f.write(data) f.close()
def get_next_consensus_wheel(self, number=1, file=conf.PLATON_CONFIG_PATH): ''' 获取下个共识轮 :param : :return: ''' data = LoadFile(file).get_data() Interval = data['EconomicModel']['Common']['Interval'] PerRoundBlocks = data['EconomicModel']['Common']['PerRoundBlocks'] ValidatorCount = data['EconomicModel']['Common']['ValidatorCount'] ConsensusSize = Interval * PerRoundBlocks * ValidatorCount ConsensusSize = ConsensusSize * number url = CommonMethod.link_list(self) platon_ppos = Ppos(url, self.address, self.chainid) current_block = platon_ppos.eth.blockNumber differ_block = ConsensusSize - (current_block % ConsensusSize) current_end_block = current_block + differ_block log.info('当前块高:{} ,下个共识轮周期结束块高:{}'.format(current_block, current_end_block)) while 1: time.sleep(self.time_interval) current_block = platon_ppos.eth.blockNumber differ_block = ConsensusSize - (current_block % ConsensusSize) log.info('当前块高度:{},还差块高:{}'.format((current_block), differ_block)) if current_block > current_end_block: break
def __reset_env(self) -> str: """ Determine whether you need to re-create a new environment based on the platon binary information and the node configuration file. :return: env_id """ env_tmp_file = os.path.join(self.cfg.env_tmp, "env.yml") if os.path.exists(self.cfg.env_tmp): if os.path.exists(env_tmp_file): env_data = LoadFile(env_tmp_file).get_data() if env_data["bin_hash"] == calc_hash(self.cfg.platon_bin_file) \ and env_data["node_hash"] == calc_hash(self.cfg.node_file): return env_data["env_id"] shutil.rmtree(self.cfg.env_tmp) os.makedirs(self.cfg.env_tmp) new_env_data = { "bin_hash": calc_hash(self.cfg.platon_bin_file), "node_hash": calc_hash(self.cfg.node_file) } env_id = new_env_data["bin_hash"] + new_env_data["node_hash"] new_env_data["env_id"] = env_id with open(env_tmp_file, "w", encoding="utf-8") as f: yaml.dump(new_env_data, f, Dumper=yaml.RoundTripDumper) return env_id
def setup_class(self): self.auto = AutoDeployPlaton() self.auto.start_all_node(self.node_yml_path) self.genesis_dict = LoadFile(self.genesis_path).get_data() self.chainid = int(self.genesis_dict["config"]["chainId"]) self.ppos_link = Ppos(self.rpc_list[0], self.address, self.chainid) self.w3_list = [connect_web3(url) for url in self.rpc_list] """用新的钱包地址和未质押过的节点id封装对象""" self.ppos_noconsensus_1 = Ppos(self.rpc_list[0], self.account_list[0], self.chainid, privatekey=self.privatekey_list[0]) self.ppos_noconsensus_2 = Ppos(self.rpc_list[0], self.account_list[1], self.chainid, privatekey=self.privatekey_list[1]) self.ppos_noconsensus_3 = Ppos(self.rpc_list[0], self.account_list[2], self.chainid, privatekey=self.privatekey_list[2]) self.ppos_noconsensus_4 = Ppos(self.rpc_list[0], self.account_list[3], self.chainid, privatekey=self.privatekey_list[3]) self.ppos_noconsensus_5 = Ppos(self.rpc_list[0], self.account_list[4], self.chainid, privatekey=self.privatekey_list[4]) self.ppos_noconsensus_6 = Ppos(self.rpc_list[0], self.account_list[5], self.chainid, privatekey=self.privatekey_list[5]) self.eth = Eth(self.w3_list[0])
def test_NE_P2P_002(global_test_env): log.info("Automatic discovery configuration test") all_node = global_test_env.get_all_nodes() # stop node if global_test_env.running: global_test_env.stop_all() # modify config file config_data = LoadFile(global_test_env.cfg.config_json_tmp).get_data() config_data['node']['P2P']['NoDiscovery'] = True with open(global_test_env.cfg.config_json_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(config_data, indent=4)) all_node = global_test_env.get_all_nodes() # upload config file global_test_env.executor(one_put_config_task, all_node) # start node global_test_env.cfg.init_chain = False global_test_env.start_all() # run ssh for node in all_node: cmd_list = run_ssh_cmd(node.ssh, "netstat -unlp | grep 16789 |wc -l") assert 0 == int(cmd_list[0][0])
def rewrite_config_json(self): """ Rewrite config :return: """ log.info("rewrite config.json") config_data = LoadFile(self.cfg.config_json_file).get_data() # config_data['node']['P2P']["BootstrapNodes"] = self.get_static_nodes() with open(self.cfg.config_json_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(config_data, indent=4))
def set_cfg(self, cfg: TestConfig): """ Set the configuration file and modify the node's cfg :param cfg: """ self.cfg = cfg genesis_config = LoadFile(self.cfg.genesis_file).get_data() self.set_genesis(genesis_config) for node in self.get_all_nodes(): node.cfg = cfg
def __init__(self, cfg: TestConfig): # env config self.cfg = cfg # these file must be exist check_file_exists(self.cfg.platon_bin_file, self.cfg.genesis_file, self.cfg.supervisor_file, self.cfg.node_file, self.cfg.address_file) if not os.path.exists(self.cfg.root_tmp): os.mkdir(self.cfg.root_tmp) # node config self.__is_update_node_file = False self.node_config = LoadFile(self.cfg.node_file).get_data() self.consensus_node_config_list = self.node_config.get("consensus", []) self.noconsensus_node_config_list = self.node_config.get( "noconsensus", []) self.node_config_list = self.consensus_node_config_list + self.noconsensus_node_config_list self.__rewrite_node_file() # node obj list self.__consensus_node_list = [] self.__normal_node_list = [] # env info self.cfg.env_id = self.__reset_env() # genesis self.genesis_config = LoadFile(self.cfg.genesis_file).get_data() # servers self.server_list = self.__parse_servers() # node self.__parse_node() # accounts self.account = Account(self.cfg.account_file, self.genesis_config["config"]["chainId"]) self.rewrite_genesis_file()
def test_token_loukup(self): #查看初始化时锁仓余额 file = conf.GENESIS_TMP_OTHER genesis_dict = LoadFile(file).get_data() FOUNDATION = genesis_dict['alloc'][conf.FOUNDATIONADDRESS] FOUNDATIONLOCKUP = self.platon_dpos1.eth.getBalance( conf.FOUNDATIONLOCKUPADDRESS) node_info = get_node_info(conf.PPOS25NODE_YML) self.rpc_list, enode_list, nodeid_list, ip_list, port_list = node_info.get( 'collusion') FOUNDATIONTOTAL = conf.TOKENTOTAL * 0.01 assert FOUNDATIONTOTAL == (FOUNDATION + FOUNDATIONLOCKUP)
def __init__(self, accountFile, chainId): """ accounts 包含的属性: address,prikey,nonce,balance,node_id,passwd :param accountFile: :param chainId: """ self.accounts = {} self.raw_accounts = LoadFile(accountFile).get_data() # log.info(self.raw_accounts) self.chain_id = chainId self.account_with_money = self.raw_accounts[0] self.reset()
def generate_genesis_json(self, genesis_json, init_node): """ 生成创世文件 :param genesis_json:创世文件保存路径 :param init_node: 初始出块节点enode :return: """ log.info("生成genesis.json") genesis_file = genesis_json genesis_data = LoadFile(self.genesis).get_data() genesis_data['config']['cbft']["initialNodes"] = init_node if not os.path.exists(os.path.dirname(genesis_file)): os.makedirs(os.path.dirname(genesis_file)) with open(genesis_file, 'w', encoding='utf-8') as f: f.write(json.dumps(genesis_data)) return genesis_file
def test_NE_P2P_004(global_test_env): log.info("Exception can not be out of the block test") # stop node if global_test_env.running: global_test_env.stop_all() # modify config file config_data = LoadFile(global_test_env.cfg.config_json_tmp).get_data() config_data['node']['P2P']['MaxPeers'] = 50 config_data['node']['P2P']['NoDiscovery'] = True config_data['node']['P2P']["BootstrapNodes"] = [] with open(global_test_env.cfg.config_json_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(config_data, indent=4)) all_node = global_test_env.get_all_nodes() # upload config file global_test_env.executor(one_put_config_task, all_node) # modify static file with open(global_test_env.cfg.static_node_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps([], indent=4)) # upload static file global_test_env.executor(one_put_static_task, all_node) # modify genesis file global_test_env.genesis_config['config']['cbft']["initialNodes"] = [] with open(global_test_env.cfg.genesis_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(global_test_env.genesis_config, indent=4)) # upload genesis file global_test_env.executor(one_put_genesis_task, all_node, global_test_env.cfg.genesis_tmp) # start node global_test_env.cfg.init_chain = False global_test_env.start_all() # check try: global_test_env.check_block() except Exception as e: log.error("check block has except:{}".format(e)) assert 0 == 0
class TestDelegate(): node_yml_path = conf.NODE_YML node_info = get_node_info(node_yml_path) rpc_list, enode_list, nodeid_list, ip_list, port_list = node_info.get( 'collusion') rpc_list2, enode_list2, nodeid_list2, ip_list2, port_list2 = node_info.get( 'nocollusion') address = Web3.toChecksumAddress(conf.ADDRESS) privatekey = conf.PRIVATE_KEY account_list = conf.account_list privatekey_list = conf.privatekey_list externalId = "1111111111" nodeName = "platon" website = "https://www.test.network" details = "supper node" programVersion = 1792 illegal_nodeID = conf.illegal_nodeID genesis_path = conf.GENESIS_TMP """替换config.json""" get_config_data() config_json_path = conf.PLATON_CONFIG_PATH config_dict = LoadFile(config_json_path).get_data() amount_delegate = Web3.fromWei( int(config_dict['EconomicModel']['Staking']['MinimumThreshold']), 'ether') amount = Web3.fromWei( int(config_dict['EconomicModel']['Staking']['StakeThreshold']), 'ether') def setup_class(self): self.auto = AutoDeployPlaton() self.auto.start_all_node(self.node_yml_path) self.genesis_dict = LoadFile(self.genesis_path).get_data() self.chainid = int(self.genesis_dict["config"]["chainId"]) self.ppos_link = Ppos( self.rpc_list[0],self.address,self.chainid) self.w3_list = [connect_web3(url) for url in self.rpc_list] """用新的钱包地址和未质押过的节点id封装对象""" self.ppos_noconsensus_1 = Ppos(self.rpc_list[0], self.account_list[0],self.chainid,privatekey=self.privatekey_list[0]) self.ppos_noconsensus_2 = Ppos(self.rpc_list[0], self.account_list[1],self.chainid,privatekey=self.privatekey_list[1]) self.ppos_noconsensus_3 = Ppos(self.rpc_list[0], self.account_list[2],self.chainid,privatekey=self.privatekey_list[2]) self.ppos_noconsensus_4 = Ppos(self.rpc_list[0], self.account_list[3],self.chainid,privatekey=self.privatekey_list[3]) self.ppos_noconsensus_5 = Ppos(self.rpc_list[0], self.account_list[4],self.chainid,privatekey=self.privatekey_list[4]) self.ppos_noconsensus_6 = Ppos(self.rpc_list[0], self.account_list[5],self.chainid,privatekey=self.privatekey_list[5]) self.eth = Eth(self.w3_list[0]) def transaction(self,w3, from_address, to_address=None,value=1000000000000000000000000000000000, gas=91000000, gasPrice=9000000000,pwd=conf.PASSWORD): """" 转账公共方法 """ personal = Personal(w3) personal.unlockAccount(from_address, pwd, 666666) params = { 'to': to_address, 'from': from_address, 'gas': gas, 'gasPrice': gasPrice, 'value': value } tx_hash = w3.eth.sendTransaction(params) result = w3.eth.waitForTransactionReceipt(HexBytes(tx_hash).hex()) return result def getCandidateList(self): """ 获取实时验证人的nodeID list """ msg = self.ppos_noconsensus_1.getCandidateList() recive_list = msg.get("Data") nodeid_list = [] if recive_list is None: return recive_list else: for node_info in recive_list: nodeid_list.append(node_info.get("NodeId")) return nodeid_list @allure.title("委托金额分别为{amount}") @pytest.mark.P1 @pytest.mark.parametrize('amount', [amount_delegate-1, 0]) def test_illege_delegate(self,amount): """ 用例id 委托金额小于门槛 """ log.info("转账每个钱包") for to_account in self.account_list: self.transaction(self.w3_list[0],self.address,to_address=to_account) log.info("质押节点1:{}成为验证人".format(self.nodeid_list2[0])) self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("钱包2委托金额") msg = self.ppos_noconsensus_2.delegate(0, self.nodeid_list2[0], amount) log.info(msg) assert msg.get("Status") == False,"委托金额异常" @allure.title("质押过的钱包委托失败") @pytest.mark.P1 def test_delegate_verifier(self): """ 测试质押过的钱包不能去委托 """ log.info("转账到钱包1") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[0]) log.info("转账到钱包2") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[1]) amount = self.amount_delegate msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[0]) if msg['Data']!= "": log.info("质押过的钱包1不能再去质押") msg = self.ppos_noconsensus_1.delegate(0, self.nodeid_list2[0], amount) # print(msg) assert msg.get("Status") == False msg_string = "is not allowed to be used for delegating" assert msg_string in msg["ErrMsg"], "质押过的钱包不能进行质押出现异常" else: log.info("质押节点1:{}成为验证人".format(self.nodeid_list2[0])) self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("质押过的钱包1不能再去质押") msg = self.ppos_noconsensus_1.delegate(0, self.nodeid_list2[0], amount) assert msg.get("Status") == False log.info(msg) msg_string = "is not allowed to be used for delegating" assert msg_string in msg["ErrMsg"], "质押过的钱包不能进行质押出现异常" @allure.title("发起委托成功") @pytest.mark.P0 def test_delegate(self): """ 用例id 95 委托成功,查询节点信息,金额 用例id 98 委托人与验证人验证,验证人存在 """ log.info("转账到钱包1") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[0]) log.info("转账到钱包2") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[1]) amount = self.amount_delegate msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[0]) if msg['Data']!= "": log.info("钱包2委托节点1") msg = self.ppos_noconsensus_2.delegate(0,self.nodeid_list2[0],amount) assert msg.get("Status") == True assert msg.get("ErrMsg") == 'ok' else: log.info("质押节点1:{}成为验证人".format(self.nodeid_list2[0])) self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) msg = self.ppos_noconsensus_2.delegate(0,self.nodeid_list2[0],amount) assert msg.get("Status") == True assert msg.get("ErrMsg") == 'ok' @allure.title("查询当前单个委托信息") @pytest.mark.P0 def test_getDelegateInfo(self): """ 用例id 94 查询当前单个委托信息 """ log.info("转账到钱包5") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[4]) log.info("转账到钱包6") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[5]) log.info("质押节点5成为验证人") self.ppos_noconsensus_5.createStaking(0, self.account_list[4], self.nodeid_list2[4], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) msg = self.ppos_noconsensus_6.delegate(0, self.nodeid_list2[4], self.amount_delegate) assert msg.get("Status") == True assert msg.get("ErrMsg") == 'ok' log.info("查询质押节点5信息") msg = self.ppos_noconsensus_5.getCandidateInfo(self.nodeid_list2[4]) assert msg["Data"]["NodeId"] == self.nodeid_list2[4] log.info("查询质押+委托的金额正确") assert Web3.fromWei(msg["Data"]["Shares"], 'ether') == self.amount + self.amount_delegate assert Web3.fromWei(msg["Data"]["ReleasedHes"], 'ether') == self.amount stakingBlockNum = msg["Data"]["StakingBlockNum"] log.info("质押的块高{}".format(stakingBlockNum)) msg = self.ppos_noconsensus_6.getDelegateInfo(stakingBlockNum, self.account_list[5], self.nodeid_list2[4]) data = msg["Data"] data = json.loads(data) assert Web3.toChecksumAddress(data["Addr"]) == self.account_list[5] assert data["NodeId"] == self.nodeid_list2[4] assert Web3.fromWei(data["ReleasedHes"], 'ether') == self.amount_delegate @allure.title("余额不足委托失败") @pytest.mark.P2 def test_insufficient_delegate(self): """ 用例96 余额不足委托失败 """ log.info("转账到钱包1") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[0]) log.info("转账到钱包2") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[1]) amount = 1000000000000000000000000000000 msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[0]) if msg['Data']!= "": msg = self.ppos_noconsensus_2.delegate(0, self.nodeid_list2[0], amount) # print(msg) assert msg.get("Status") == False assert msg.get("ErrMsg") == 'Delegate failed: The von of account is not enough' else: log.info("质押节点1:{}成为验证人".format(self.nodeid_list2[0])) self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) msg = self.ppos_noconsensus_2.delegate(0, self.nodeid_list2[0], amount) # print(msg) assert msg.get("Status") == False assert msg.get("ErrMsg") == 'Delegate failed: The von of account is not enough' @allure.title("验证人不存在进行委托") @pytest.mark.P2 def test_not_nodeId_delegate(self): """ 用例72 验证人不存在进行委托 """ log.info("转账到钱包2") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[1]) value = self.amount_delegate nodeid = conf.illegal_nodeID msg = self.ppos_noconsensus_2.delegate(0, nodeid, value) print(msg) assert msg.get("Status") == False assert msg.get("ErrMsg") == 'This candidate is not exist' @allure.title("验证人退出后,委托人信息还存在") @pytest.mark.P1 def test_back_unStaking_commissioned(self): """ 用例id 82 验证人申请退回质押金,委托金额还生效 用例id 83 验证人退出后,委托人信息还存在 """ log.info("转账到钱包1") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[0]) log.info("转账到钱包2") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[1]) msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[0]) if msg['Data']== "": log.info("节点1再次成为验证人") self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("钱包2进行委托100") self.ppos_noconsensus_2.delegate(0, self.nodeid_list2[0], 100) log.info("节点1退出验证人") self.ppos_noconsensus_1.unStaking(self.nodeid_list2[0]) msg = self.ppos_noconsensus_2.getDelegateListByAddr(self.account_list[1]) log.info(msg) StakingBlockNum = msg["Data"][0]["StakingBlockNum"] msg = self.ppos_noconsensus_2.getDelegateInfo(StakingBlockNum,self.account_list[1],self.nodeid_list2[0]) log.info(msg) data = msg["Data"] data = json.loads(data) log.info(data) assert Web3.toChecksumAddress(data["Addr"]) == self.account_list[1] assert data["NodeId"] == self.nodeid_list2[0] else: log.info("钱包2进行委托100") self.ppos_noconsensus_2.delegate(0, self.nodeid_list2[0], 100) log.info("节点1退出验证人") self.ppos_noconsensus_1.unStaking(self.nodeid_list2[0]) msg = self.ppos_noconsensus_2.getDelegateListByAddr(self.account_list[1]) log.info(msg) StakingBlockNum = msg["Data"][0]["StakingBlockNum"] msg = self.ppos_noconsensus_2.getDelegateInfo(StakingBlockNum,self.account_list[1],self.nodeid_list2[0]) log.info(msg) data = msg["Data"] data = json.loads(data) log.info(data) assert Web3.toChecksumAddress(data["Addr"]) == self.account_list[1] assert data["NodeId"] == self.nodeid_list2[0] @allure.title("验证节点退出后,再成为验证节点,钱包委托信息有2个") @pytest.mark.P2 def test_identifier_quit_delegate(self): """ 委托验证节点,验证节点退出后,再成为验证节点,再去委托:预期有2个委托消息 """ log.info("转账到钱包3") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[2]) log.info("转账到钱包4") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[3]) log.info("质押节点3:{}成为验证节点".format(self.nodeid_list2[2])) self.ppos_noconsensus_3.createStaking(0, self.account_list[2], self.nodeid_list2[2], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("钱包4:{}进行委托".format(self.account_list[3])) self.ppos_noconsensus_4.delegate(0,self.nodeid_list2[2],50) log.info("质押节点3退出验证人{}".format(self.nodeid_list2[2])) self.ppos_noconsensus_3.unStaking(self.nodeid_list2[2]) log.info("{}再次成为验证人".format(self.nodeid_list2[2])) self.ppos_noconsensus_3.createStaking(0, self.account_list[2],self.nodeid_list2[2],self.externalId, self.nodeName, self.website, self.details,self.amount,self.programVersion) log.info("钱包4:{}再次进行委托".format(self.account_list[3])) msg = self.ppos_noconsensus_4.delegate(0,self.nodeid_list2[2],100) print(msg) log.info("查询钱包的委托情况") msg = self.ppos_noconsensus_4.getDelegateListByAddr(self.account_list[3]) log.info(msg) log.info(msg["Data"]) print(len(msg["Data"])) assert len(msg["Data"]) == 2 for i in msg["Data"]: assert Web3.toChecksumAddress(i["Addr"]) == self.account_list[3] assert i["NodeId"] == self.nodeid_list2[2]
class TestEnvironment: def __init__(self, cfg: TestConfig): # env config self.cfg = cfg # these file must be exist check_file_exists(self.cfg.platon_bin_file, self.cfg.genesis_file, self.cfg.supervisor_file, self.cfg.node_file, self.cfg.address_file) if not os.path.exists(self.cfg.root_tmp): os.mkdir(self.cfg.root_tmp) # node config self.__is_update_node_file = False self.node_config = LoadFile(self.cfg.node_file).get_data() self.consensus_node_config_list = self.node_config.get("consensus", []) self.noconsensus_node_config_list = self.node_config.get( "noconsensus", []) self.node_config_list = self.consensus_node_config_list + self.noconsensus_node_config_list self.__rewrite_node_file() # node obj list self.__consensus_node_list = [] self.__normal_node_list = [] # env info self.cfg.env_id = self.__reset_env() # genesis self.genesis_config = LoadFile(self.cfg.genesis_file).get_data() # servers self.server_list = self.__parse_servers() # node self.__parse_node() # accounts self.account = Account(self.cfg.account_file, self.genesis_config["config"]["chainId"]) self.rewrite_genesis_file() @property def consensus_node_list(self) -> List[Node]: return self.__consensus_node_list @property def normal_node_list(self) -> List[Node]: return self.__normal_node_list @property def chain_id(self): return self.genesis_config["config"]["chainId"] @property def amount(self): return self.genesis_config["config"]["cbft"]["amount"] @property def period(self): return self.genesis_config["config"]["cbft"]["period"] @property def validatorMode(self): return self.genesis_config["config"]["cbft"]["validatorMode"] @property def version(self): return "0.13.2" @property def running(self) -> bool: """ Determine if all nodes are running :return: bool """ for node in self.get_all_nodes(): if not node.running: return False return True @property def max_byzantium(self) -> int: """ Maximum number of Byzantine nodes """ return get_f(self.consensus_node_config_list) @property def block_interval(self) -> int: """ Block interval """ period = self.genesis_config["config"]["cbft"].get("period") amount = self.genesis_config["config"]["cbft"].get("amount") return int(period / 1000 / amount) def consensus_node_id_list(self) -> List[str]: return [node.node_id for node in self.consensus_node_list] def find_node_by_node_id(self, node_id): for node in self.get_all_nodes(): if node_id == node.node_id: return node raise Exception("can't find node") def copy_env(self): """ Copy environment """ return copy.copy(self) def set_cfg(self, cfg: TestConfig): """ Set the configuration file and modify the node's cfg :param cfg: """ self.cfg = cfg genesis_config = LoadFile(self.cfg.genesis_file).get_data() self.rewrite_genesis_file() self.set_genesis(genesis_config) for node in self.get_all_nodes(): node.cfg = cfg def set_genesis(self, genesis_config: dict): """ Set the genesis and modify the genesis of the node. :param genesis_config: """ self.genesis_config = genesis_config self.account.chain_id = self.chain_id for node in self.get_all_nodes(): node.chain_id = self.chain_id def __reset_env(self) -> str: """ Determine whether you need to re-create a new environment based on the platon binary information and the node configuration file. :return: env_id """ env_tmp_file = os.path.join(self.cfg.env_tmp, "env.yml") if os.path.exists(self.cfg.env_tmp): if os.path.exists(env_tmp_file): env_data = LoadFile(env_tmp_file).get_data() if env_data["bin_hash"] == calc_hash(self.cfg.platon_bin_file) \ and env_data["node_hash"] == calc_hash(self.cfg.node_file): return env_data["env_id"] shutil.rmtree(self.cfg.env_tmp) os.makedirs(self.cfg.env_tmp) new_env_data = { "bin_hash": calc_hash(self.cfg.platon_bin_file), "node_hash": calc_hash(self.cfg.node_file) } env_id = new_env_data["bin_hash"] + new_env_data["node_hash"] new_env_data["env_id"] = env_id with open(env_tmp_file, "w", encoding="utf-8") as f: yaml.dump(new_env_data, f, Dumper=yaml.RoundTripDumper) return env_id def get_init_nodes(self) -> List[dict]: """ Get the list of init nodes :return: list """ init_node_list = [] for node in self.consensus_node_list: init_node_list.append({ "node": node.enode, "blsPubKey": node.blspubkey }) return init_node_list def get_static_nodes(self) -> list: """ Get static node enode list :return: list """ static_node_list = [] for node in self.get_all_nodes(): static_node_list.append(node.enode) return static_node_list def get_all_nodes(self) -> List[Node]: """ Get all node objects :return: Node object """ return self.__consensus_node_list + self.__normal_node_list def get_rand_node(self) -> Node: """ Randomly obtain a consensus node :return: Node object """ return random.choice(self.consensus_node_list) def get_consensus_node_by_index(self, index) -> Node: """ Get a consensus node based on the index :param index: :return: Node object """ return self.__consensus_node_list[index] def get_normal_node_by_index(self, index) -> Node: """ Get a normal node based on the index :param index: :return: Node object """ return self.__normal_node_list[index] def get_a_normal_node(self) -> Node: """ Get the first normal node :return: Node object """ return self.__normal_node_list[0] def executor(self, func, data_list, *args) -> bool: with ThreadPoolExecutor(max_workers=self.cfg.max_worker) as exe: futures = [exe.submit(func, pair, *args) for pair in data_list] done, unfinished = wait(futures, timeout=30, return_when=ALL_COMPLETED) result = [] for d in done: is_success, msg = d.result() if not is_success: result.append(msg) if len(result) > 0: raise Exception("executor {} failed:{}".format( func.__name__, result)) return True def deploy_all(self, genesis_file=None): """ Deploy all nodes and start :param genesis_file: Specify genesis, do not pass the default generated using tmp """ self.account.reset() self.prepare_all() if genesis_file is None: genesis_file = self.cfg.genesis_tmp log.info("deploy all node") self.deploy_nodes(self.get_all_nodes(), genesis_file) time.sleep(10) log.info("deploy success") def prepare_all(self): """ Prepare environmental data """ self.rewrite_genesis_file() self.rewrite_static_nodes() self.rewrite_config_json() self.__compression() if self.cfg.install_supervisor: self.install_all_supervisor() self.cfg.install_supervisor = False if self.cfg.install_dependency: self.install_all_dependency() self.cfg.install_dependency = False self.put_all_compression() def start_all(self): """ Start all nodes, judge whether to initialize according to the value of cfg init_chain """ log.info("start all node") self.start_nodes(self.get_all_nodes(), self.cfg.init_chain) def stop_all(self): """ Stop all nodes """ log.info("stop all node") self.stop_nodes(self.get_all_nodes()) def reset_all(self): """ Restart all nodes """ log.info("restart all node") self.reset_nodes(self.get_all_nodes()) def clean_all(self): """ Close all nodes and delete the directory of the deployment node """ log.info("clean all node") self.clean_nodes(self.get_all_nodes()) def clean_db_all(self): """ Close all nodes and delete the database """ log.info("clean db all node") self.clean_db_nodes(self.get_all_nodes()) def shutdown(self): """ Close all nodes and delete the node deployment directory, supervisor node configuration """ log.info("shutdown and clean all nodes") def close(node: Node): return node.close() return self.executor(close, self.get_all_nodes()) def clean_supervisor_confs(self): def clean(server: Server): return server.clean_supervisor_conf() return self.executor(clean, self.server_list) def start_nodes(self, node_list: List[Node], init_chain=True): """ Boot node :param node_list: :param init_chain: """ def start(node: Node, need_init_chain): return node.start(need_init_chain) return self.executor(start, node_list, init_chain) def deploy_nodes(self, node_list: List[Node], genesis_file): """ Deployment node Choose whether to empty the environment depending on whether initialization is required Upload all node files :param node_list: :param genesis_file: """ log.info("deploy node") if self.cfg.init_chain: self.clean_nodes(node_list) self.put_file_nodes(node_list, genesis_file) return self.start_nodes(node_list, self.cfg.init_chain) def put_file_nodes(self, node_list: List[Node], genesis_file): """ Upload all files :param node_list: :param genesis_file: """ def prepare(node: Node): return node.put_all_file(genesis_file) return self.executor(prepare, node_list) def stop_nodes(self, node_list: List[Node]): """ Close node :param node_list: """ def stop(node: Node): return node.stop() return self.executor(stop, node_list) def reset_nodes(self, node_list: List[Node]): """ Restart node :param node_list: """ def restart(node: Node): return node.restart() return self.executor(restart, node_list) def clean_nodes(self, node_list: List[Node]): """ Close the node and delete the node data :param node_list: :return: """ def clean(node: Node): return node.clean() return self.executor(clean, node_list) def clean_db_nodes(self, node_list: List[Node]): """ Close the node and clear the node database :param node_list: """ def clean_db(node: Node): return node.clean_db() return self.executor(clean_db, node_list) def __parse_node(self): """ Instantiate all nodes """ def init(node_config): return Node(node_config, self.cfg, self.chain_id) log.info("parse node to node object") with ThreadPoolExecutor(max_workers=self.cfg.max_worker) as executor: futures = [ executor.submit(init, pair) for pair in self.consensus_node_config_list ] done, unfinished = wait(futures, timeout=30, return_when=ALL_COMPLETED) for do in done: self.__consensus_node_list.append(do.result()) if self.noconsensus_node_config_list: with ThreadPoolExecutor( max_workers=self.cfg.max_worker) as executor: futures = [ executor.submit(init, pair) for pair in self.noconsensus_node_config_list ] done, unfinished = wait(futures, timeout=30, return_when=ALL_COMPLETED) for do in done: self.__normal_node_list.append(do.result()) def put_all_compression(self): """ Upload compressed file """ log.info("upload compression") def uploads(server: Server): return server.put_compression() return self.executor(uploads, self.server_list) def install_all_dependency(self): """ Installation dependence """ log.info("install rely") def install(server: Server): return server.install_dependency() return self.executor(install, self.server_list) def install_all_supervisor(self): """ Install supervisor """ log.info("install supervisor") def install(server: Server): return server.install_supervisor() return self.executor(install, self.server_list) def __parse_servers(self) -> List[Server]: """ Instantiate all servers """ server_config_list, server_list = [], [] def check_in(_ip, nodes): for n in nodes: if _ip == n["host"]: return True return False for node_config in self.node_config_list: ip = node_config["host"] if check_in(ip, server_config_list): continue server_config_list.append(node_config) def init(config): return Server(config, self.cfg) with ThreadPoolExecutor(max_workers=self.cfg.max_worker) as executor: futures = [ executor.submit(init, pair) for pair in server_config_list ] done, unfinished = wait(futures, timeout=30, return_when=ALL_COMPLETED) for do in done: server_list.append(do.result()) return server_list def block_numbers(self, node_list: List[Node] = None) -> dict: """ Get the block height of the incoming node :param node_list: """ if node_list is None: node_list = self.get_all_nodes() result = {} for node in node_list: result[node.node_mark] = node.block_number return result def check_block(self, need_number=10, multiple=3, node_list: List[Node] = None): """ Verify the highest block in the current chain :param need_number: :param multiple: :param node_list: """ if node_list is None: node_list = self.get_all_nodes() use_time = int(need_number * self.block_interval * multiple) while use_time: if max(self.block_numbers(node_list).values()) < need_number: time.sleep(1) use_time -= 1 continue return raise Exception("The environment is not working properly") def backup_all_logs(self, case_name: str): """ Download all node logs """ return self.backup_logs(self.get_all_nodes(), case_name) def backup_logs(self, node_list: List[Node], case_name): """ Backup log :param node_list: :param case_name: """ self.__check_log_path() def backup(node: Node): return node.backup_log() self.executor(backup, node_list) return self.__zip_all_log(case_name) def __check_log_path(self): if not os.path.exists(self.cfg.tmp_log): os.mkdir(self.cfg.tmp_log) else: shutil.rmtree(self.cfg.tmp_log) os.mkdir(self.cfg.tmp_log) if not os.path.exists(self.cfg.bug_log): os.mkdir(self.cfg.bug_log) def __zip_all_log(self, case_name): log.info("Start compressing.....") t = time.strftime("%Y%m%d%H%M%S", time.localtime()) tar_name = "{}/{}_{}.tar.gz".format(self.cfg.bug_log, case_name, t) tar = tarfile.open(tar_name, "w:gz") tar.add(self.cfg.tmp_log, arcname=os.path.basename(self.cfg.tmp_log)) tar.close() log.info("Compression completed") log.info("Start deleting the cache.....") shutil.rmtree(self.cfg.tmp_log) log.info("Delete cache complete") return os.path.basename(tar_name) def rewrite_genesis_file(self): """ Rewrite genesis """ log.info("rewrite genesis.json") self.genesis_config['config']['cbft'][ "initialNodes"] = self.get_init_nodes() # with open(self.cfg.address_file, "r", encoding="UTF-8") as f: # key_dict = json.load(f) # account = key_dict["address"] # self.genesis_config['alloc'][account] = {"balance": str(99999999999999999999999999)} accounts = self.account.get_all_accounts() for account in accounts: if account.get('id') == 3: continue self.genesis_config['alloc'][account['address']] = { "balance": str(account['balance']) } with open(self.cfg.genesis_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(self.genesis_config, indent=4)) def rewrite_static_nodes(self): """ Rewrite static """ log.info("rewrite static-nodes.json") static_nodes = self.get_static_nodes() with open(self.cfg.static_node_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(static_nodes, indent=4)) def rewrite_config_json(self): """ Rewrite config :return: """ log.info("rewrite config.json") config_data = LoadFile(self.cfg.config_json_file).get_data() # config_data['node']['P2P']["BootstrapNodes"] = self.get_static_nodes() with open(self.cfg.config_json_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(config_data, indent=4)) def __fill_node_config(self, node_config: dict): """ Fill in the node file with some necessary values :param node_config: """ if not node_config.get("id") or not node_config.get("nodekey"): self.__is_update_node_file = True node_config["nodekey"], node_config["id"] = generate_key() if not node_config.get("blsprikey") or not node_config.get( "blspubkey"): self.__is_update_node_file = True node_config["blsprikey"], node_config[ "blspubkey"] = generate_blskey() if not node_config.get("port"): self.__is_update_node_file = True node_config["port"] = 16789 if not node_config.get("rpcport"): self.__is_update_node_file = True node_config["rpcport"] = 6789 if not node_config.get("url"): self.__is_update_node_file = True node_config["url"] = "http://{}:{}".format(node_config["host"], node_config["rpcport"]) if node_config.get("wsport"): self.__is_update_node_file = True node_config["wsurl"] = "ws://{}:{}".format(node_config["host"], node_config["wsport"]) return node_config def __rewrite_node_file(self): log.info("rewrite node file") result, result_consensus_list, result_noconsensus_list = {}, [], [] if len(self.consensus_node_config_list) >= 1: for node_config in self.consensus_node_config_list: result_consensus_list.append( self.__fill_node_config(node_config)) result["consensus"] = result_consensus_list if self.noconsensus_node_config_list and len( self.noconsensus_node_config_list) >= 1: for node_config in self.noconsensus_node_config_list: result_noconsensus_list.append( self.__fill_node_config(node_config)) result["noconsensus"] = result_noconsensus_list if self.__is_update_node_file: self.consensus_node_config_list = result_consensus_list self.noconsensus_node_config_list = result_noconsensus_list with open(self.cfg.node_file, encoding="utf-8", mode="w") as f: yaml.dump(result, f, Dumper=yaml.RoundTripDumper) def __compression(self): """ Compressed file """ log.info("compression data") env_gz = os.path.join(self.cfg.env_tmp, self.cfg.env_id) if os.path.exists(env_gz): return os.makedirs(env_gz) data_dir = os.path.join(env_gz, "data") os.makedirs(data_dir) keystore_dir = os.path.join(data_dir, "keystore") os.makedirs(keystore_dir) keystore = os.path.join(keystore_dir, os.path.basename(self.cfg.address_file)) shutil.copyfile(self.cfg.address_file, keystore) shutil.copyfile(self.cfg.platon_bin_file, os.path.join(env_gz, "platon")) shutil.copyfile(self.cfg.config_json_tmp, os.path.join(env_gz, "config.json")) t = tarfile.open(env_gz + ".tar.gz", "w:gz") t.add(env_gz, arcname=os.path.basename(env_gz)) t.close()
def __init__(self, node_yml_path, cbft_json_path): node1, node2 = get_node_list(node_yml_path) self.node_list = node1 + node2 key_list = ["node" + str(i) for i in range(1, 1 + len(self.node_list))] self.node_dict = dict(zip(key_list, self.node_list)) cbft_dict = LoadFile(cbft_json_path).get_data() self.address = Web3.toChecksumAddress(conf.ADDRESS) self.address_candidate = Web3.toChecksumAddress( "0x03f0E0a226f081A5dAeCFdA222caFc959eD7B800") self.private_candidate = "11e20dc277fafc4bc008521adda4b79c2a9e403131798c94eacb071005d43532" self.address_refund = Web3.toChecksumAddress( "0x2B645d169998eb0447A21D0c48a1780d115251a9") self.private_refund = "6382b6fc972ae9c22a2d8913dace308d09e406d118efddb702a7ea9e505cc823" self.address_vote = Web3.toChecksumAddress( "0x1E1ae3407377F7897470FEf31a80873B4FD75cA1") self.private_vote = "f7aa4dc6fceed0f099d0466ce2136a2cf3b500b15e8286572f39198b562a3bdb" self.pwd = conf.PASSWORD self.ticket_price = Web3.fromWei( int(cbft_dict['ppos']['ticket']['ticketPrice']), 'ether') self.allowed = int(cbft_dict['ppos']['candidate']['allowed']) self.total_ticket = int(cbft_dict['ppos']['ticket']['maxCount']) self.abi = conf.DPOS_CONTRACT_ABI self.platon_dpos = PlatonDpos(self.node_list[1]["url"], self.address, self.pwd, abi=self.abi) # self.w3_list = [connect_web3(node["url"]) for node in self.node_list] # self.new_address = Web3.toChecksumAddress( # self.platon_dpos1.web3.personal.newAccount(self.pwd)) self.platon_dpos.web3.personal.unlockAccount(self.address, self.pwd, 88888899) self.send_data = { "to": self.address_vote, "from": self.address, "gas": '9000', "gasPrice": '1000000000', "value": Web3.toWei(1000000, 'ether'), } self.platon_dpos.eth.sendTransaction(self.send_data) self.platon_dpos.eth.sendTransaction(self.send_data) self.platon_dpos.eth.sendTransaction(self.send_data) self.platon_dpos.eth.sendTransaction(self.send_data) self.platon_dpos.eth.sendTransaction(self.send_data) self.platon_dpos.eth.sendTransaction(self.send_data) self.platon_dpos.eth.sendTransaction(self.send_data) tx_hash = self.platon_dpos.eth.sendTransaction(self.send_data) self.platon_dpos.eth.waitForTransactionReceipt(tx_hash) balance = self.platon_dpos.eth.getBalance(self.address_vote) log.info(balance) self.send_data = { "to": self.address_refund, "from": self.address, "gas": '9000', "gasPrice": '1000000000', "value": Web3.toWei(100000, 'ether'), } tx_hash = self.platon_dpos.eth.sendTransaction(self.send_data) self.platon_dpos.eth.waitForTransactionReceipt(tx_hash) self.fee = int(1000).to_bytes(4, 'big') self.extra = "Test" self.node_number = len(self.node_dict.keys())
class TestDpos: node_yml_path = conf.NODE_YML cbft_json_path = conf.CBFT2 node_info = get_node_info(node_yml_path) rpc_list, enode_list, nodeid_list, ip_list, port_list = node_info.get( 'collusion') rpc_list2, enode_list2, nodeid_list2, ip_list2, port_list2 = node_info.get( 'nocollusion') cbft_dict = LoadFile(cbft_json_path).get_data() address = Web3.toChecksumAddress(conf.ADDRESS) pwd = conf.PASSWORD ticket_price = Web3.fromWei( int(cbft_dict['ppos']['ticket']['ticketPrice']), 'ether') allowed = int(cbft_dict['ppos']['candidate']['allowed']) total_ticket = int(cbft_dict['ppos']['ticket']['maxCount']) rpc_list += rpc_list2 enode_list += enode_list2 nodeid_list += nodeid_list2 ip_list += ip_list2 port_list += port_list2 key_list = ["node" + str(i) for i in range(1, 1 + len(rpc_list))] rpc_dict = dict(zip(key_list, rpc_list)) enode_dict = dict(zip(key_list, enode_list)) nodeid_dict = dict(zip(key_list, nodeid_list)) ip_dict = dict(zip(key_list, ip_list)) port_dict = dict(zip(key_list, port_list)) abi = conf.DPOS_CONTRACT_ABI def setup_class(self): self.auto = AutoDeployPlaton(cbft=self.cbft_json_path) self.auto.start_all_node(self.node_yml_path) self.platon_dpos1 = PlatonDpos( self.rpc_list[0], self.address, self.pwd, abi=self.abi) self.w3_list = [connect_web3(url) for url in self.rpc_list] self.new_address = Web3.toChecksumAddress( self.platon_dpos1.web3.personal.newAccount(self.pwd)) self.send_data = { "to": self.new_address, "from": self.address, "gas": '9000', "gasPrice": '1000000000', "value": self.w3_list[0].toWei(100000, 'ether'), } tx_hash = self.platon_dpos1.eth.sendTransaction(self.send_data) self.platon_dpos1.eth.waitForTransactionReceipt(tx_hash) self.platon_dpos2 = PlatonDpos( self.rpc_list[0], self.new_address, self.pwd, abi=self.abi) self.fee = int(1000).to_bytes(4, 'big') self.extra = "Test" # def teardown_class(self): # self.auto.start_all_node(self.node_yml_path) def check_event(self, msg): event_data, func_name = msg func_name += "Event" assert func_name in event_data, "{}中不包含{}键".format( event_data, func_name) event = event_data[func_name][0] event = json.loads(event) assert event["Ret"], "质押结果状态错误" assert event["ErrMsg"] == "success", "质押结果msg错误" def test_candidate_deposit(self): ''' @Description: 质押节点,使其成为候选人 @param {type} @@@@ @return: @@@@ ''' result = self.platon_dpos1.CandidateDeposit(self.nodeid_dict['node5'], self.new_address, self.fee, self.ip_dict['node5'], self.port_dict['node5'], self.extra, value=100) self.check_event(result) candidate_info = self.platon_dpos1.GetCandidateDetails( self.nodeid_dict['node5']) assert isinstance(candidate_info, dict), "返回结果错误{}".format( candidate_info) assert candidate_info["Deposit"] == self.platon_dpos1.web3.toWei( 100, 'ether') assert candidate_info["Host"] == self.ip_dict["node5"], "质押ip与传输的ip不一致" assert candidate_info["CandidateId"] == self.nodeid_dict["node5"], "质押nodeid与传输的不一致" assert candidate_info["Port"] == self.port_dict['node5'], "质押端口与传输的不一致,获取port:{},实际质押port:{}".format( candidate_info["Port"], self.port_dict['node5']) assert self.platon_dpos1.web3.toChecksumAddress( candidate_info["Owner"]) == self.new_address, "质押地址不正确" candidate_list = self.platon_dpos2.GetCandidateList() # 校验candidate_list包含节点179 assert candidate_info in candidate_list, "候选人列表不包含节点{}".format( self.ip_dict['node5']) # @pytest.mark.skip # def add_pledge(self): # ''' # 已不支持增加质押,用例暂不执行 # 增加质押 # :return: # ''' # result = self.platon_dpos1.CandidateDeposit(self.nodeid_dict['node5'], self.new_address, self.fee, # self.ip_dict['node5'], # self.port_dict['node5'], self.extra, value=10) # self.check_event(result) # candidate_info = self.platon_dpos1.GetCandidateDetails( # self.nodeid_dict['node5']) # # candidate_info为节点179的质押信息 # assert isinstance(candidate_info, dict), "返回结果错误{}".format( # candidate_info) # assert candidate_info["Deposit"] == self.platon_dpos1.web3.toWei( # 60, 'ether') # @pytest.mark.skip # def test_refund_10(self): # ''' # 已不支持部分退款,用例暂不执行 # @Description: 查询退款金额低于10% # @param {type} @@@@ # @return: @@@@ # ''' # i = 500000000000000000 # status = 0 # try: # self.platon_dpos2.CandidateApplyWithdraw( # self.nodeid_dict['node5'], i) # except: # status = 1 # assert status == 1, "低于10%应不允许提取" def test_refund(self): ''' @Description: 查询退款是否正常,是否退出候选人列表 @param {type} @@@@ @return: @@@@ ''' i = 50000000000000000000 start_balance = self.platon_dpos2.eth.getBalance(self.new_address) result = self.platon_dpos2.CandidateDeposit(self.nodeid_dict['node6'], self.new_address, self.fee, self.ip_dict['node6'], self.port_dict['node6'], self.extra, value=50) candidate_info = self.platon_dpos1.GetCandidateDetails( self.nodeid_dict['node6']) self.check_event(result) result = self.platon_dpos2.CandidateApplyWithdraw( self.nodeid_dict['node6'], i) self.check_event(result) time.sleep(3) withdraw_list = self.platon_dpos2.GetCandidateWithdrawInfos( self.nodeid_dict['node6']) assert withdraw_list["Balance"] == i, "申请退款的金额与查询结果不一致" result = self.platon_dpos1.CandidateWithdraw(self.nodeid_dict["node6"]) self.check_event(result) end_balance = self.platon_dpos1.eth.getBalance(self.new_address) assert end_balance - start_balance < 100000000000000000, "退款金额错误,退款前:{}|退款后:{}".format( self.platon_dpos1.web3.fromWei(start_balance, 'ether'), self.platon_dpos1.web3.fromWei(end_balance, 'ether')) candidate_list = self.platon_dpos1.GetCandidateList() assert candidate_info not in candidate_list, "node6还在候选人列表中" def test_candidate_sort(self): ''' @Description: 候选人排序 @param {type} @@@@ @return: @@@@ ''' # result_1 = self.platon_dpos1.CandidateDeposit(self.nodeid_dict['node5'], self.new_address, self.fee, # self.ip_dict['node5'], # self.port_dict['node5'], self.extra, value=45) # self.check_event(result_1) result_2 = self.platon_dpos1.CandidateDeposit(self.nodeid_dict['node6'], self.new_address, self.fee, self.ip_dict['node6'], self.port_dict['node6'], self.extra, value=160) self.check_event(result_2) candidate_list = self.platon_dpos1.GetCandidateList() candidate_info = self.platon_dpos1.GetCandidateDetails( self.nodeid_dict['node6']) assert candidate_list[0] == candidate_info, "候选人列表排序错误" def test_candidate_cap(self): ''' @Description: 候选人列表容量 @param {type} @@@@ @return: @@@@ ''' status = 0 candidate_info = self.platon_dpos1.GetCandidateDetails( self.nodeid_dict['node5']) result_1 = self.platon_dpos1.CandidateDeposit(self.nodeid_dict['node1'], self.new_address, self.fee, self.ip_dict['node1'], self.port_dict['node1'], self.extra, value=131) self.check_event(result_1) result_2 = self.platon_dpos1.CandidateDeposit(self.nodeid_dict['node2'], self.new_address, self.fee, self.ip_dict['node2'], self.port_dict['node2'], self.extra, value=135) self.check_event(result_2) result_3 = self.platon_dpos1.CandidateDeposit(self.nodeid_dict['node3'], self.new_address, self.fee, self.ip_dict['node3'], self.port_dict['node3'], self.extra, value=135) self.check_event(result_3) result_4 = self.platon_dpos1.CandidateDeposit(self.nodeid_dict['node4'], self.new_address, self.fee, self.ip_dict['node4'], self.port_dict['node4'], self.extra, value=140) self.check_event(result_4) candidate_list = self.platon_dpos1.GetCandidateList() log.info("入围节点列表:{}".format(candidate_list)) assert candidate_info not in candidate_list, "node5还在候选人列表中" def test_ticket_price(self): '''校验票价是否与配置文件中一致''' price = self.platon_dpos1.GetTicketPrice() config_price = Web3.toWei(self.ticket_price, 'ether') assert config_price == price, '实际票价:{},与配置文件中:{},不一致'.format( config_price, price) def test_vote_ticket(self): '''投票''' value = self.allowed * self.ticket_price vote_info, _ = self.platon_dpos1.VoteTicket(self.allowed, self.ticket_price, self.nodeid_dict['node6'], self.new_address, value) self.platon_dpos1.VoteTicket(self.allowed, self.ticket_price, self.nodeid_dict['node1'], self.new_address, value) self.platon_dpos1.VoteTicket(self.allowed, self.ticket_price, self.nodeid_dict['node2'], self.new_address, value) self.platon_dpos1.VoteTicket(self.allowed, self.ticket_price, self.nodeid_dict['node3'], self.new_address, value) vote_info, _ = self.platon_dpos1.VoteTicket(self.allowed - 1, self.ticket_price, self.nodeid_dict['node4'], self.new_address, value - 1) assert 'success' in vote_info['VoteTicketEvent'][0], '投票失败,结果:{}'.format( vote_info) # @pytest.skip # def test_ticket_detail(self): # ''' # 接口已经删除,用例屏蔽 # 验证节点下选票数量、选票的详细信息 # ''' # ticket_ids = self.platon_dpos1.GetCandidateTicketIds(self.nodeid_dict['node1']) # ticket_num = len(ticket_ids) # assert ticket_num == self.allowed, '节点选票数:{}与已投票数:{}不一致'.format(ticket_num, self.allowed) # ticket_detail = self.platon_dpos1.GetTicketDetail(ticket_ids[0]) # owner = Web3.toChecksumAddress(ticket_detail[0]['Owner']) # assert owner == self.new_address, '投票人:{}与投票时用的钱包地址:{}不一致'.format(owner, self.new_address) # dposite = ticket_detail[0]['Deposit'] # price = Web3.toWei(self.ticket_price, 'ether') # assert dposite == price, '投票金额:{}与票价:{}不一致'.format(dposite, price) # candidateid = ticket_detail[0]['CandidateId'] # assert candidateid == self.nodeid_dict['node1'], '票详情中节点id:{},与投票时节点id不一致:{}'.format(candidateid, # self.nodeid_dict['node1']) # @pytest.skip # def test_batch_ticket_detail(self): # ''' # 接口已删除,用例屏蔽 # 验证批量获取节点下选票数量、选票的详细信息 # ''' # batch_ticket_ids = self.platon_dpos1.GetBatchCandidateTicketIds( # [self.nodeid_dict['node1'], self.nodeid_dict['node2']]) # print('batch_ticket_ids = ', batch_ticket_ids) # ticket_ids = batch_ticket_ids[0].get(self.nodeid_dict['node1']) # ticket_ids_one = self.platon_dpos1.GetCandidateTicketIds(self.nodeid_dict['node1']) # assert ticket_ids == ticket_ids_one, '批量获取详情{}\n单独获取详情{}不一致'.format(ticket_ids, ticket_ids_one) # node1_tickets = batch_ticket_ids[0].get(self.nodeid_dict['node1']) # node2_tickets = batch_ticket_ids[0].get(self.nodeid_dict['node2']) # ticket_details = self.platon_dpos1.GetBatchTicketDetail([node1_tickets[0], node2_tickets[0]]) # ticket_detail = ticket_details[0] # ticket_detail_one = self.platon_dpos1.GetTicketDetail(ticket_details[0]['TicketId'])[0] # assert ticket_detail == ticket_detail_one, '批量获取的票详情{}与单独查询票详情不一致{}'.format(ticket_detail, ticket_detail_one) # assert len(ticket_details) == 2, '批量获取票详情数{}不等于请求数2'.format(len(ticket_details)) def test_vote_undpos_node(self): '''向非备选池节点投票''' value = self.allowed * self.ticket_price status = 0 try: self.platon_dpos1.VoteTicket(self.allowed, self.ticket_price, self.nodeid_dict['node5'], self.new_address, value) except: status = 1 assert status, '不在备选池的节点不能投票成功' def test_ticket_pool_remainder(self): '''验证票池剩余数量''' remaind = self.platon_dpos1.GetPoolRemainder() should_remaind = self.total_ticket - (self.allowed * 5 - 1) assert remaind == should_remaind, '票池剩余票:{}与已消费后应剩余数:{}不一致'.format( remaind, should_remaind) # @pytest.skip # def test_get_candidate_epoch(self): # ''' # 获取票龄详情接口已删除,无法获取选票产生区块,用例无法验证 # 该接口以后会去掉,用例暂不运行 # 验证候选人票龄 # ''' # ticket_ids = self.platon_dpos1.GetCandidateTicketIds(self.nodeid_dict['node1']) # vote_block_number = self.platon_dpos1.GetTicketDetail(ticket_ids[0])[0]['BlockNumber'] # should_epoch = (self.platon_dpos1.eth.blockNumber - vote_block_number + 1) * len(ticket_ids) # epoch = self.platon_dpos1.GetCandidateEpoch(self.nodeid_dict['node1']) # assert epoch == should_epoch, '候选人票龄计算结果:{},与预期结果:{}不一致'.format(epoch, should_epoch) def test_get_candidate_ticket_count(self): '''批量查询候选节点的有效选票数量''' ctc_dict = self.platon_dpos1.GetCandidateTicketCount( '{}:{}:{}:{}'.format(self.nodeid_dict['node1'], self.nodeid_dict['node2'], self.nodeid_dict['node3'], self.nodeid_dict['node4'])) count1 = int(ctc_dict.get(self.nodeid_dict['node1'])) count2 = int(ctc_dict.get(self.nodeid_dict['node2'])) count3 = int(ctc_dict.get(self.nodeid_dict['node3'])) count4 = int(ctc_dict.get(self.nodeid_dict['node4'])) assert count1 == self.allowed, '候选节点有效选票数量{},与预期结果{}不一致'.format( count1, self.allowed) assert count2 == self.allowed, '候选节点有效选票数量{},与预期结果{}不一致'.format( count2, self.allowed) assert count3 == self.allowed, '候选节点有效选票数量{},与预期结果{}不一致'.format( count3, self.allowed) assert count4 == self.allowed - \ 1, '候选节点有效选票数量{},与预期结果{}不一致'.format(count4, self.allowed) # def test_get_ticket_count_by_tx_hash(self): # '''批量查询交易的有效选票数量''' # _, tx_hash1 = self.platon_dpos1.VoteTicket( # self.allowed, 1, self.nodeid_dict['node1'], self.address, 10) # _, tx_hash2 = self.platon_dpos1.VoteTicket( # self.allowed, 1, self.nodeid_dict['node2'], self.address, 10) # _, tx_hash3 = self.platon_dpos1.VoteTicket( # self.allowed, 1, self.nodeid_dict['node3'], self.address, 10) # _, tx_hash4 = self.platon_dpos1.VoteTicket( # self.allowed, 1, self.nodeid_dict['node4'], self.address, 10) # tc_dict = self.platon_dpos1.GetTicketCountByTxHash( # '{}:{}:{}:{}'.format(tx_hash1, tx_hash2, tx_hash3, tx_hash4)) # assert tc_dict.get(tx_hash1) == self.allowed, '交易的有效选票数量{},与预期结果{}不一致'.format(tc_dict.get(tx_hash1), # self.allowed) # assert tc_dict.get(tx_hash2) == self.allowed, '交易的有效选票数量{},与预期结果{}不一致'.format(tc_dict.get(tx_hash2), # self.allowed) # assert tc_dict.get(tx_hash3) == self.allowed, '交易的有效选票数量{},与预期结果{}不一致'.format(tc_dict.get(tx_hash3), # self.allowed) # assert tc_dict.get(tx_hash4) == self.allowed, '交易的有效选票数量{},与预期结果{}不一致'.format(tc_dict.get(tx_hash4), # self.allowed) def test_verifiers(self): ''' @Description: 验证人为候选人列表的前四,幸运票奖励发放 @param {type} @@@@ @return: @@@@ ''' before_reward = self.platon_dpos1.eth.getBalance(self.new_address) candidate_list = self.platon_dpos1.GetCandidateList() log.info("新的的入围节点列表:{}".format(candidate_list)) candidate_id = [i['CandidateId'] for i in candidate_list] block_number = self.platon_dpos1.eth.blockNumber sleep_time = get_sleep_time(block_number) time.sleep(sleep_time) verfier_info_list = self.platon_dpos1.GetVerifiersList() log.info("验证人列表:{}".format(verfier_info_list)) assert len(verfier_info_list) > 0,"查询结果异常,验证人列表为空。" verfier_list = [info['CandidateId'] for info in verfier_info_list] assert verfier_list == candidate_id[:4], "验证人没有取候选人的前四,验证人id:{}\n候选人id:{}".format(verfier_list, candidate_list[:4]) status = 1 for verfier in verfier_list: if self.nodeid_dict['node4'] in verfier: status = 0 assert status, '投票不达到门槛不能成为见证人' # 校验幸运选票是否发放奖励 after_reward = self.platon_dpos1.eth.getBalance(self.new_address) assert after_reward > before_reward, '见证人奖励未发放,发放前余额:{},发放后余额:{}'.format( before_reward, after_reward) def test_verify_transaction(self): ''' @Description: 切换验证人后,测试交易是否成功,所有节点块高是否一致 @param {type} @@@@ @return: @@@@ ''' tx_hash = self.platon_dpos1.eth.sendTransaction(self.send_data) self.platon_dpos1.eth.waitForTransactionReceipt(tx_hash) block_list = [] for w in self.w3_list: block_list.append(w.eth.blockNumber) assert min(block_list) > 60, "区块没有正常增加" assert max(block_list) - min(block_list) < 5, "各节点区块高度差距过高" time.sleep(60) w3 = Web3(Web3.HTTPProvider(self.rpc_dict["node6"])) assert w3.net.peerCount >= 3, "节点node6连接的节点数少于3个"
def reset_config(global_test_env): yield config_data = LoadFile(global_test_env.cfg.config_json_tmp).get_data() with open(global_test_env.cfg.config_json_tmp, 'w', encoding='utf-8') as f: f.write(json.dumps(config_data, indent=4)) global_test_env.deploy_all()
class TestLockup(): node_yml_path = conf.NODE_YML node_info = get_node_info(node_yml_path) rpc_list, enode_list, nodeid_list, ip_list, port_list = node_info.get( 'collusion') rpc_list2, enode_list2, nodeid_list2, ip_list2, port_list2 = node_info.get( 'nocollusion') address = Web3.toChecksumAddress(conf.ADDRESS) privatekey = conf.PRIVATE_KEY account_list = conf.account_list privatekey_list = conf.privatekey_list externalId = "1111111111" nodeName = "platon" website = "https://www.test.network" details = "supper node" programVersion = 1792 illegal_nodeID = conf.illegal_nodeID genesis_path = conf.GENESIS_TMP get_config_data() config_json_path = conf.PLATON_CONFIG_PATH config_dict = LoadFile(config_json_path).get_data() amount_delegate = Web3.fromWei( int(config_dict['EconomicModel']['Staking']['MinimumThreshold']), 'ether') amount = Web3.fromWei( int(config_dict['EconomicModel']['Staking']['StakeThreshold']), 'ether') def setup_class(self): self.auto = AutoDeployPlaton() self.auto.start_all_node(self.node_yml_path) self.genesis_dict = LoadFile(self.genesis_path).get_data() self.chainid = int(self.genesis_dict["config"]["chainId"]) self.ppos_link = Ppos(self.rpc_list[0], self.address, self.chainid) self.w3_list = [connect_web3(url) for url in self.rpc_list] """用新的钱包地址和未质押过的节点id封装对象""" self.ppos_noconsensus_1 = Ppos(self.rpc_list[0], self.account_list[0], self.chainid, privatekey=self.privatekey_list[0]) self.ppos_noconsensus_2 = Ppos(self.rpc_list[0], self.account_list[1], self.chainid, privatekey=self.privatekey_list[1]) self.ppos_noconsensus_3 = Ppos(self.rpc_list[0], self.account_list[2], self.chainid, privatekey=self.privatekey_list[2]) self.ppos_noconsensus_4 = Ppos(self.rpc_list[0], self.account_list[3], self.chainid, privatekey=self.privatekey_list[3]) self.ppos_noconsensus_5 = Ppos(self.rpc_list[0], self.account_list[4], self.chainid, privatekey=self.privatekey_list[4]) self.ppos_noconsensus_6 = Ppos(self.rpc_list[0], self.account_list[5], self.chainid, privatekey=self.privatekey_list[5]) self.eth = Eth(self.w3_list[0]) def transaction(self, w3, from_address, to_address=None, value=100000000000000000000000000000000, gas=91000000, gasPrice=9000000000, pwd=conf.PASSWORD): """" 转账公共方法,转账1000w eth """ personal = Personal(w3) personal.unlockAccount(from_address, pwd, 666666) params = { 'to': to_address, 'from': from_address, 'gas': gas, 'gasPrice': gasPrice, 'value': value } tx_hash = w3.eth.sendTransaction(params) result = w3.eth.waitForTransactionReceipt(HexBytes(tx_hash).hex()) return result def getCandidateList(self): """ 获取实时验证人的nodeID list """ msg = self.ppos_noconsensus_1.getCandidateList() recive_list = msg.get("Data") nodeid_list = [] if recive_list is None: return recive_list else: for node_info in recive_list: nodeid_list.append(node_info.get("NodeId")) return nodeid_list @allure.title("验证人退回质押金(未到达可解锁期)") @pytest.mark.P0 def test_back_unstaking(self): """ 验证人退回质押金(未到达可解锁期) 质押成为下个周期验证人,退出后,下一个结算周期退出 """ log.info("转账每个钱包") for to_account in self.account_list: self.transaction(self.w3_list[0], self.address, to_address=to_account) log.info("节点1质押金额{} eth".format(self.amount)) self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) account_1 = self.eth.getBalance(self.account_list[0]) log.info(account_1) get_block_number(self.w3_list[0]) log.info("查询第2个结算周期的验证人") node_list = getVerifierList() log.info(node_list) assert self.nodeid_list2[0] in node_list log.info("节点1在第2结算周期,锁定期申请退回") self.ppos_noconsensus_1.unStaking(nodeId=self.nodeid_list2[0]) """发起退回消耗一定gas""" account_2 = self.eth.getBalance(self.account_list[0]) log.info(account_2) assert account_1 > account_2, "发起退回的交易钱包异常" log.info("进入第3个结算周期") get_block_number(w3=self.w3_list[0]) account_3 = self.eth.getBalance(self.account_list[0]) log.info(account_3) assert account_3 > account_2 assert account_3 - account_2 < Web3.toWei(self.amount, "ether") log.info(account_3 - account_2) node_list = getVerifierList() log.info(node_list) assert self.nodeid_list2[0] not in node_list log.info("进入第4个结算周期") get_block_number(w3=self.w3_list[0]) account_4 = self.eth.getBalance(self.account_list[0]) log.info(account_4) """ 第3个结算周期结束后质押金额已退 """ log.info(account_4 - account_3) assert account_4 - account_3 > Web3.toWei(self.amount, "ether") assert account_4 - account_2 > Web3.toWei(self.amount, "ether") @allure.title("锁定期增加质押与委托") @pytest.mark.P0 def test_lockup_addstaking(self): """ 用例id74 锁定期增加质押 用例id 112 锁定期委托人进行委托 """ log.info("转账每个钱包") for to_account in self.account_list: self.transaction(self.w3_list[0], self.address, to_address=to_account) msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[0]) if msg["Data"] == "": log.info("节点1质押金额{} eth".format(self.amount)) self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("进入锁定期") get_block_number(self.w3_list[0]) value = 100 msg = self.ppos_noconsensus_1.addStaking(self.nodeid_list2[0], 0, value) assert msg.get("Status") == True msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[0]) log.info(msg) nodeid = msg["Data"]["NodeId"] log.info("增持后验证质押金额") assert msg["Data"]["Shares"] == 1000100000000000000000000 assert msg["Data"]["Released"] == 1000000000000000000000000 assert msg["Data"]["ReleasedHes"] == 100000000000000000000 assert nodeid == self.nodeid_list2[0] self.ppos_noconsensus_2.delegate(0, self.nodeid_list2[0], 10) msg = self.ppos_noconsensus_2.getCandidateInfo(self.nodeid_list2[0]) log.info(msg) assert msg["Data"]["Shares"] == 1000110000000000000000000 stakingBlockNum = msg["Data"]["StakingBlockNum"] msg = self.ppos_noconsensus_2.getDelegateInfo(stakingBlockNum, self.account_list[1], self.nodeid_list2[0]) data = msg["Data"] data = json.loads(data) assert Web3.toChecksumAddress(data["Addr"]) == self.account_list[1] assert data["NodeId"] == self.nodeid_list2[0] # assert Web3.fromWei(data["ReleasedHes"], 'ether') == 10 @allure.title("验证根据质押+委托金额金额排名") @pytest.mark.P2 def test_taking_cycle_ranking(self): """ 验证根据质押金额排名 """ log.info("转账每个钱包") for to_account in self.account_list: self.transaction(self.w3_list[0], self.address, to_address=to_account) log.info("质押节点2") self.ppos_noconsensus_2.createStaking(0, self.account_list[1], self.nodeid_list2[1], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("质押节点3") self.ppos_noconsensus_3.createStaking(0, self.account_list[2], self.nodeid_list2[2], self.externalId, self.nodeName, self.website, self.details, self.amount + 130, self.programVersion) log.info("进入到下个结算周期") get_block_number(w3=self.w3_list[0]) node_list = getVerifierList() log.info(node_list) msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[1]) log.info(msg) msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[2]) log.info(msg) assert self.nodeid_list2[2] in node_list assert self.nodeid_list2[1] in node_list assert self.nodeid_list2[2] == node_list[0] log.info("钱包4委托节点2 70eth") msg = self.ppos_noconsensus_4.delegate(0, nodeId=self.nodeid_list2[1], amount=70) print(msg) log.info("节点2增加质押61 eth") msg = self.ppos_noconsensus_2.addStaking(self.nodeid_list2[1], 0, amount=61) print(msg) log.info("进入下一个结算周期") get_block_number(self.w3_list[0]) node_list = getVerifierList() log.info(node_list) log.info(self.nodeid_list2[1]) log.info(self.nodeid_list2[2]) """预期节点2排在节点3之前""" msg = self.ppos_noconsensus_2.getCandidateInfo(self.nodeid_list2[1]) log.info(msg) msg = self.ppos_noconsensus_3.getCandidateInfo(self.nodeid_list2[2]) log.info(msg) assert node_list[0] == self.nodeid_list2[1] assert node_list[1] == self.nodeid_list2[2] @allure.title("质押相等的金额,按照时间先早排序") @pytest.mark.P1 def test_same_amount_cycle(self): """ 质押相等的金额,按照时间先早排序 """ self.auto = AutoDeployPlaton() self.auto.start_all_node(self.node_yml_path) log.info("转账每个钱包") for to_account in self.account_list: self.transaction(self.w3_list[0], self.address, to_address=to_account) log.info("质押节点4金额200eth") self.ppos_noconsensus_4.createStaking(0, self.account_list[3], self.nodeid_list2[3], self.externalId, self.nodeName, self.website, self.details, self.amount + 200, self.programVersion) log.info("质押节点5金额200eth") self.ppos_noconsensus_5.createStaking(0, self.account_list[4], self.nodeid_list2[4], self.externalId, self.nodeName, self.website, self.details, self.amount + 200, self.programVersion) log.info("进入到下个结算周期") get_block_number(self.w3_list[0]) node_list = getVerifierList() log.info(node_list) log.info(self.nodeid_list2[3]) log.info(self.nodeid_list2[4]) assert node_list[0] == self.nodeid_list2[3] assert node_list[1] == self.nodeid_list2[4] @allure.title("验证人申请退回所有质押金(包含初始质押金和当前结算期内质押金)") @pytest.mark.P2 def test_unstaking_all(self): log.info("转账每个钱包") for to_account in self.account_list: self.transaction(self.w3_list[0], self.address, to_address=to_account) value_before = self.eth.getBalance(self.account_list[5]) log.info(value_before) self.ppos_noconsensus_6.createStaking(0, self.account_list[5], self.nodeid_list2[5], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("进入第2个结算周期") get_block_number(self.w3_list[0]) log.info("节点6增持金额") self.ppos_noconsensus_6.addStaking(self.nodeid_list2[5], 0, self.amount + 1000) log.info("进入第3个结算周期") get_block_number(self.w3_list[0]) log.info("节点6发起退回") self.ppos_noconsensus_6.unStaking(nodeId=self.nodeid_list2[5]) log.info("进入第4个结算周期") get_block_number(self.w3_list[0]) value = self.eth.getBalance(self.account_list[5]) log.info(value) assert value < value_before, "钱还在锁定期,预期未退回,实际异常" log.info("进入第5个结算周期") get_block_number(self.w3_list[0]) value_after = self.eth.getBalance(self.account_list[5]) log.info(value_after) log.info(value_after - value_before) amount_sum = self.amount * 2 + 1000 log.info(Web3.toWei(amount_sum, "ether")) assert value_after > value_before, "出块奖励异常" assert value_after > value + Web3.toWei( amount_sum, "ether"), "解锁期的余额大于锁定期的余额+质押+增持金额,但是发生异常" @allure.title("根据金额排名,从高到低排名") @pytest.mark.P0 def test_ranking(self): """ 测试根据金额排名,从高到低排名 """ self.auto = AutoDeployPlaton() self.auto.start_all_node(self.node_yml_path) log.info("转账每个钱包") for to_account in self.account_list: self.transaction(self.w3_list[0], self.address, to_address=to_account) self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount + 50, self.programVersion) self.ppos_noconsensus_2.createStaking(0, self.account_list[1], self.nodeid_list2[1], self.externalId, self.nodeName, self.website, self.details, self.amount + 40, self.programVersion) self.ppos_noconsensus_3.createStaking(0, self.account_list[2], self.nodeid_list2[2], self.externalId, self.nodeName, self.website, self.details, self.amount + 30, self.programVersion) self.ppos_noconsensus_4.createStaking(0, self.account_list[3], self.nodeid_list2[3], self.externalId, self.nodeName, self.website, self.details, self.amount + 20, self.programVersion) self.ppos_noconsensus_5.createStaking(0, self.account_list[4], self.nodeid_list2[4], self.externalId, self.nodeName, self.website, self.details, self.amount + 10, self.programVersion) self.ppos_noconsensus_6.createStaking(0, self.account_list[5], self.nodeid_list2[5], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("进入下个周期") get_block_number(self.w3_list[0]) node_list = getVerifierList() log.info(node_list) """根据config配置验证人数""" # assert self.nodeid_list2[5] not in node_list assert node_list[0] == self.nodeid_list2[0] assert node_list[1] == self.nodeid_list2[1] assert node_list[2] == self.nodeid_list2[2] assert node_list[3] == self.nodeid_list2[3] assert node_list[4] == self.nodeid_list2[4] assert node_list[5] == self.nodeid_list2[-1]
class TestAddstaking(): node_yml_path = conf.NODE_YML node_info = get_node_info(node_yml_path) rpc_list, enode_list, nodeid_list, ip_list, port_list = node_info.get( 'collusion') rpc_list2, enode_list2, nodeid_list2, ip_list2, port_list2 = node_info.get( 'nocollusion') address = Web3.toChecksumAddress(conf.ADDRESS) pwd = conf.PASSWORD privatekey = conf.PRIVATE_KEY account_list = conf.account_list privatekey_list = conf.privatekey_list externalId = "1111111111" nodeName = "platon" website = "https://www.test.network" details = "supper node" programVersion = 1792 illegal_nodeID = conf.illegal_nodeID genesis_path = conf.GENESIS_TMP """替换config.json""" get_config_data() config_json_path = conf.PLATON_CONFIG_PATH config_dict = LoadFile(config_json_path).get_data() amount_delegate = Web3.fromWei( int(config_dict['EconomicModel']['Staking']['MinimumThreshold']), 'ether') amount = Web3.fromWei( int(config_dict['EconomicModel']['Staking']['StakeThreshold']), 'ether') def setup_class(self): self.auto = AutoDeployPlaton() self.auto.start_all_node(self.node_yml_path) self.genesis_dict = LoadFile(self.genesis_path).get_data() self.chainid = int(self.genesis_dict["config"]["chainId"]) self.ppos_link = Ppos(self.rpc_list[0], self.address, self.chainid) self.ppos_link1 = Ppos(self.rpc_list[1], self.address, self.chainid) self.w3_list = [connect_web3(url) for url in self.rpc_list] """用新的钱包地址和未质押过的节点id封装对象""" self.ppos_noconsensus_1 = Ppos(self.rpc_list[0], self.account_list[0], self.chainid, privatekey=self.privatekey_list[0]) self.ppos_noconsensus_2 = Ppos(self.rpc_list[0], self.account_list[1], self.chainid, privatekey=self.privatekey_list[1]) self.ppos_noconsensus_3 = Ppos(self.rpc_list[0], self.account_list[2], self.chainid, privatekey=self.privatekey_list[2]) self.ppos_noconsensus_4 = Ppos(self.rpc_list[0], self.account_list[3], self.chainid, privatekey=self.privatekey_list[3]) self.ppos_noconsensus_5 = Ppos(self.rpc_list[0], self.account_list[4], self.chainid, privatekey=self.privatekey_list[4]) self.ppos_noconsensus_6 = Ppos(self.rpc_list[0], self.account_list[5], self.chainid, privatekey=self.privatekey_list[5]) self.eth = Eth(self.w3_list[0]) def transaction(self, w3, from_address, to_address=None, value=1000000000000000000000000000000000, gas=91000000, gasPrice=9000000000, pwd="88888888"): """" 转账公共方法 """ personal = Personal(w3) personal.unlockAccount(from_address, pwd, 666666) params = { 'to': to_address, 'from': from_address, 'gas': gas, 'gasPrice': gasPrice, 'value': value } tx_hash = w3.eth.sendTransaction(params) result = w3.eth.waitForTransactionReceipt(HexBytes(tx_hash).hex()) return result def getCandidateList(self): """ 获取实时验证人的nodeID list """ msg = self.ppos_noconsensus_1.getCandidateList() recive_list = msg.get("Data") nodeid_list = [] if recive_list is None: return recive_list else: for node_info in recive_list: nodeid_list.append(node_info.get("NodeId")) return nodeid_list @allure.title("增加质押分别为{amount}") @pytest.mark.P1 @pytest.mark.parametrize('amount', [100, 10000000, 1000000]) def test_add_staking(self, amount): """ 用例id 72 账户余额足够,增加质押成功 用例id 74 验证人在质押锁定期内增持的质押数量不限制 """ log.info("转账到钱包1") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[0]) nodeId = self.nodeid_list2[0] log.info("钱包1做一笔质押") self.ppos_noconsensus_1.createStaking(0, self.account_list[0], nodeId, self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("分别验证增持{}".format(amount)) msg = self.ppos_noconsensus_1.addStaking(nodeId, typ=0, amount=amount) print(msg) assert msg.get("Status") == True, "返回状态错误" assert msg.get("ErrMsg") == 'ok', "返回消息错误" msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[0]) nodeid = msg["Data"]["NodeId"] assert nodeid == self.nodeid_list2[0] if amount == 100: assert Web3.fromWei(msg["Data"]["Shares"], 'ether') == self.amount + 100 if amount == 10000000: assert Web3.fromWei(msg["Data"]["Shares"], 'ether') == self.amount + 100 + 10000000 if amount == 1000000: assert Web3.fromWei( msg["Data"]["Shares"], 'ether') == self.amount + 100 + 10000000 + 1000000 @allure.title("非验证人增持质押") @pytest.mark.P2 def test_not_illegal_addstaking(self): """ 用例id 78 非验证人增持质押 """ log.info("转账到钱包1") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[0]) nodeId = conf.illegal_nodeID msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[0]) if msg['Data'] == "": log.info("节点1成为验证人") self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) msg = self.ppos_noconsensus_1.addStaking(nodeId=nodeId, typ=0, amount=100) assert msg.get("Status") == False, "返回状态错误" assert msg.get("ErrMsg") == 'This candidate is not exist', "非验证人增持质押异常" @allure.title("编辑验证人信息-未成为验证人的nodeID") @pytest.mark.P1 def test_editCandidate_nodeid(self): """ 验证修改未成为验证人的nodeID """ externalId = "88888888" nodeName = "wuyiqin" website = "www://baidu.com" details = "node_1" account = self.account_list[0] nodeid = conf.illegal_nodeID self.transaction(self.w3_list[0], self.address, to_address=self.account_list[1]) log.info("转账到钱包2") nodeId = self.nodeid_list2[1] msg = self.ppos_noconsensus_2.getCandidateInfo(nodeId) if msg['Data'] == "": log.info("节点2成为验证人") msg = self.ppos_noconsensus_2.createStaking( 0, self.account_list[1], nodeId, self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) assert msg.get("Status") == True, "返回状态错误" assert msg.get("ErrMsg") == 'ok', "返回消息错误" log.info("节点2修改节点信息") msg = self.ppos_noconsensus_2.updateStakingInfo( account, nodeid, externalId, nodeName, website, details) log.info(msg) assert msg.get("Status") == False, "返回状态错误" @allure.title("编辑验证人信息-参数有效性验证") @pytest.mark.P0 def test_editCandidate(self): """ 用例id 70 编辑验证人信息-参数有效性验证 """ externalId = "88888888" nodeName = "wuyiqin" website = "www://baidu.com" details = "node_1" account = self.account_list[0] self.transaction(self.w3_list[0], self.address, to_address=self.account_list[1]) log.info("转账到钱包2") nodeId = self.nodeid_list2[1] msg = self.ppos_noconsensus_2.getCandidateInfo(nodeId) if msg['Data'] == "": log.info("节点2成为验证人") msg = self.ppos_noconsensus_2.createStaking( 0, self.account_list[1], nodeId, self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) assert msg.get("Status") == True, "返回状态错误" assert msg.get("ErrMsg") == 'ok', "返回消息错误" log.info("节点2修改节点信息") msg = self.ppos_noconsensus_2.updateStakingInfo( account, self.nodeid_list2[1], externalId, nodeName, website, details) assert msg.get("Status") == True, "返回状态错误" assert msg.get("ErrMsg") == 'ok', "返回消息错误" log.info("查看节点2的信息") msg = self.ppos_noconsensus_2.getCandidateInfo(self.nodeid_list2[1]) log.info(msg) assert msg["Data"]["ExternalId"] == externalId assert msg["Data"]["NodeName"] == nodeName assert msg["Data"]["Website"] == website assert msg["Data"]["Details"] == details log.info(self.account_list[0]) BenefitAddress = Web3.toChecksumAddress(msg["Data"]["BenefitAddress"]) log.info(BenefitAddress) assert BenefitAddress == account @allure.title("修改钱包地址,更改后的地址收益正常") @pytest.mark.P2 def test_alter_address(self): """ 修改钱包地址,更改后的地址收益正常 """ log.info("转账到钱包2") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[1]) externalId = "88888888" nodeName = "helloword" website = "www://dddddd.com" details = "node_2" ####没钱的钱包##### account = conf.no_money[0] balance_before = self.eth.getBalance(account) assert balance_before == 0 msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[1]) if msg['Data'] == "": log.info("质押节点2成为验证节点") msg = self.ppos_noconsensus_2.createStaking( 0, self.account_list[0], self.nodeid_list2[1], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) assert msg.get("Status") == True, "返回状态错误" assert msg.get("ErrMsg") == 'ok', "返回消息错误" log.info("修改节点2的信息") msg = self.ppos_noconsensus_2.updateStakingInfo( account, self.nodeid_list2[1], externalId, nodeName, website, details) assert msg.get("Status") == True, "返回状态错误" assert msg.get("ErrMsg") == 'ok', "返回消息错误" log.info("进入第2个结算周期") get_block_number(self.w3_list[0]) log.info("进入第3个结算周期") get_block_number(self.w3_list[0]) balance_after = self.eth.getBalance(account) log.info(balance_after) assert balance_after > 0, "修改后的钱包余额没增加" assert balance_after > balance_before, "地址更改后未发现余额增加" @allure.title("增加质押为{x}") @pytest.mark.P2 @pytest.mark.parametrize('x', [0, (amount_delegate - 1)]) def test_add_staking_zero(self, x): """测试增持金额为0,低于门槛""" log.info("转账到钱包3") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[2]) log.info("质押节点3,成为验证人") nodeId = self.nodeid_list2[2] self.ppos_noconsensus_3.createStaking(0, self.account_list[2], nodeId, self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("节点3增持质押".format(x)) msg = self.ppos_noconsensus_3.addStaking(nodeId, typ=0, amount=x) log.info(msg) assert msg.get("Status") == False, "返回状态错误" @allure.title("账户余额不足增加质押") @pytest.mark.P2 def test_Insufficient_addStaking(self): """ 用例id 73 账户余额不足,增加质押失败 """ log.info("转账到钱包5") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[4]) log.info("质押节点5成为验证人") nodeId = self.nodeid_list2[4] msg = self.ppos_noconsensus_5.createStaking( 0, self.account_list[4], nodeId, self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) assert msg.get("Status") == True, "返回状态错误" amount = 100000000000000000000000000000000000 msg = self.ppos_noconsensus_5.addStaking(nodeId=nodeId, typ=0, amount=amount) assert msg.get("Status") == False, "返回状态错误" msg_string = "The von of account is not enough" assert msg_string in msg.get("ErrMsg"), "余额不足发生质押异常" # @allure.title("验证人已申请退出中,申请增持质押") # def test_quit_and_addstaking(self): # """ # 用例id 77 验证人已申请退出中,申请增持质押 # """ # nodeId = self.nodeid_list2[0] # msg = self.ppos_noconsensus_1.unStaking(nodeId) # assert msg.get("Status") == True, "返回状态错误" # assert msg.get("ErrMsg") == 'ok', "返回消错误" # log.info("{}已经退出验证人.".format(nodeId)) # node_list = self.getCandidateList() # log.info(self.nodeid_list2[0]) # log.info(node_list) # assert self.nodeid_list2[0] not in node_list # """验证人退出后,查询实时验证人列表返回的是空,可能是bug""" # msg = self.ppos_noconsensus_1.addStaking(nodeId, typ=0, amount=100) # assert msg.get("Status") == True, "返回状态错误" # assert msg.get("ErrMsg") == 'This candidate is not exist' @allure.title("验证人已申请退出中,申请增持质押") @pytest.mark.P1 def test_quit_and_addstaking(self): """ 用例id 77 验证人已申请退出中,申请增持质押 """ log.info("转账到钱包4") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[3]) nodeId = self.nodeid_list2[3] log.info("节点4发起质押") msg = self.ppos_noconsensus_4.createStaking( 0, self.account_list[3], nodeId, self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) assert msg.get("Status") == True, "质押失败" log.info("节点4退出质押") msg = self.ppos_noconsensus_4.unStaking(nodeId) # print(msg) assert msg.get("Status") == True, "返回状态错误" assert msg.get("ErrMsg") == 'ok', "返回消息错误" log.info("{}已经退出验证人.".format(nodeId)) node_list = self.getCandidateList() # print(nodeId) # print(node_list) assert nodeId not in node_list msg = self.ppos_noconsensus_1.getCandidateInfo(nodeId) assert msg['Data'] == "" msg = self.ppos_noconsensus_4.addStaking(nodeId, typ=0, amount=100) assert msg.get("Status") == False, "返回状态错误" assert msg.get("ErrMsg") == 'This candidate is not exist'
from common.load_file import LoadFile, get_node_info node_yml_path = conf.PPOS_NODE_YML node_info = get_node_info(node_yml_path) rpc_list, enode_list, nodeid_list, ip_list, port_list = node_info.get( 'collusion') rpc_list2, enode_list2, nodeid_list2, ip_list2, port_list2 = node_info.get( 'nocollusion') address = Web3.toChecksumAddress(conf.ADDRESS) privatekey = conf.PRIVATE_KEY account_list = conf.account_list privatekey_list = conf.privatekey_list genesis_path = conf.GENESIS_TMP genesis_dict = LoadFile(genesis_path).get_data() chainid = int(genesis_dict["config"]["chainId"]) config_json_path = conf.PLATON_CONFIG_PATH data = LoadFile(config_json_path).get_data() ExpectedMinutes = data['EconomicModel']['Common']['ExpectedMinutes'] Interval = data['EconomicModel']['Common']['Interval'] PerRoundBlocks = data['EconomicModel']['Common']['PerRoundBlocks'] ValidatorCount = data['EconomicModel']['Common']['ValidatorCount'] Consensuswheel = (ExpectedMinutes * 60) // (Interval * PerRoundBlocks * ValidatorCount) ConsensusSize = Consensuswheel * (Interval * PerRoundBlocks * ValidatorCount) StakeThreshold = 1000000000000000000000000 MinimumThreshold = 10000000000000000000
class TestUndelegate(): node_yml_path = conf.NODE_YML node_info = get_node_info(node_yml_path) rpc_list, enode_list, nodeid_list, ip_list, port_list = node_info.get( 'collusion') rpc_list2, enode_list2, nodeid_list2, ip_list2, port_list2 = node_info.get( 'nocollusion') address = Web3.toChecksumAddress(conf.ADDRESS) privatekey = conf.PRIVATE_KEY account_list = conf.account_list privatekey_list = conf.privatekey_list externalId = "1111111111" nodeName = "platon" website = "https://www.test.network" details = "supper node" programVersion = 1792 illegal_nodeID = conf.illegal_nodeID genesis_path = conf.GENESIS_TMP """替换config.json""" get_config_data() config_json_path = conf.PLATON_CONFIG_PATH config_dict = LoadFile(config_json_path).get_data() amount_delegate = Web3.fromWei( int(config_dict['EconomicModel']['Staking']['MinimumThreshold']), 'ether') amount = Web3.fromWei( int(config_dict['EconomicModel']['Staking']['StakeThreshold']), 'ether') def setup_class(self): self.auto = AutoDeployPlaton() self.auto.start_all_node(self.node_yml_path) self.genesis_dict = LoadFile(self.genesis_path).get_data() self.chainid = int(self.genesis_dict["config"]["chainId"]) self.ppos_link = Ppos(self.rpc_list[0], self.address, self.chainid) self.w3_list = [connect_web3(url) for url in self.rpc_list] """用新的钱包地址和未质押过的节点id封装对象""" self.ppos_noconsensus_1 = Ppos(self.rpc_list[0], self.account_list[0], self.chainid, privatekey=self.privatekey_list[0]) self.ppos_noconsensus_2 = Ppos(self.rpc_list[0], self.account_list[1], self.chainid, privatekey=self.privatekey_list[1]) self.ppos_noconsensus_3 = Ppos(self.rpc_list[0], self.account_list[2], self.chainid, privatekey=self.privatekey_list[2]) self.ppos_noconsensus_4 = Ppos(self.rpc_list[0], self.account_list[3], self.chainid, privatekey=self.privatekey_list[3]) self.ppos_noconsensus_5 = Ppos(self.rpc_list[0], self.account_list[4], self.chainid, privatekey=self.privatekey_list[4]) self.ppos_noconsensus_6 = Ppos(self.rpc_list[0], self.account_list[5], self.chainid, privatekey=self.privatekey_list[5]) self.eth = Eth(self.w3_list[0]) def transaction(self, w3, from_address, to_address=None, value=1000000000000000000000000000000000, gas=91000000, gasPrice=9000000000, pwd=conf.PASSWORD): """" 转账公共方法 """ personal = Personal(w3) personal.unlockAccount(from_address, pwd, 666666) params = { 'to': to_address, 'from': from_address, 'gas': gas, 'gasPrice': gasPrice, 'value': value } tx_hash = w3.eth.sendTransaction(params) result = w3.eth.waitForTransactionReceipt(HexBytes(tx_hash).hex()) return result def getCandidateList(self): """ 获取实时验证人的nodeID list """ msg = self.ppos_noconsensus_1.getCandidateList() recive_list = msg.get("Data") nodeid_list = [] if recive_list is None: return recive_list else: for node_info in recive_list: nodeid_list.append(node_info.get("NodeId")) return nodeid_list ##############################赎回#################################################### @allure.title("委托人未达到锁定期申请赎回") @pytest.mark.P0 def test_unDelegate_part(self): """ 用例id 106 申请赎回委托 用例id 111 委托人未达到锁定期申请赎回 申请部分赎回 """ log.info("转账到钱包3") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[2]) log.info("转账到钱包4") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[3]) msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[2]) if msg['Data'] == "": log.info("质押节点3:{}成为验证节点".format(self.nodeid_list2[2])) self.ppos_noconsensus_3.createStaking(0, self.account_list[2], self.nodeid_list2[2], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("钱包4 {}委托到3 {}".format(self.account_list[3], self.account_list[2])) value = 100 self.ppos_noconsensus_4.delegate(0, self.nodeid_list2[2], value) log.info("查询当前节点质押信息") msg = self.ppos_noconsensus_3.getCandidateInfo(self.nodeid_list2[2]) stakingBlockNum = msg["Data"]["StakingBlockNum"] log.info("发起质押的区高{}".format(stakingBlockNum)) delegate_value = 20 self.ppos_noconsensus_4.unDelegate(stakingBlockNum, self.nodeid_list2[2], delegate_value) log.info("查询钱包{}的委托信息".format(self.account_list[3])) msg = self.ppos_noconsensus_4.getDelegateInfo(stakingBlockNum, self.account_list[3], self.nodeid_list2[2]) print(msg) data = msg["Data"] """不清楚msg["Data"]对应value是str类型,需要再转字典""" data = json.loads(data) print(data) assert Web3.toChecksumAddress(data["Addr"]) == self.account_list[3] assert data["NodeId"] == self.nodeid_list2[2] print(data["ReleasedHes"]) value = value - delegate_value result_value = Web3.toWei(value, "ether") assert data["ReleasedHes"] == result_value @allure.title("大于委托金额赎回") @pytest.mark.P0 def test_unDelegate_iff(self): """ 验证 大于委托金额赎回 """ msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[2]) if msg['Data'] == "": log.info("质押节点3成为验证节点") self.ppos_noconsensus_3.createStaking(0, self.account_list[2], self.nodeid_list2[2], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) log.info("钱包4 委托到3 {}") value = 100 self.ppos_noconsensus_4.delegate(0, self.nodeid_list2[2], value) msg = self.ppos_noconsensus_3.getCandidateInfo(self.nodeid_list2[2]) stakingBlockNum = msg["Data"]["StakingBlockNum"] msg = self.ppos_noconsensus_4.getDelegateInfo(stakingBlockNum, self.account_list[3], self.nodeid_list2[2]) data = msg["Data"] """不清楚msg["Data"]对应value是str类型,需要再转字典""" data = json.loads(data) releasedHes = data["ReleasedHes"] releasedHes = Web3.fromWei(releasedHes, 'ether') log.info("委托钱包可赎回的金额单位eth:{}".format(releasedHes)) delegate_value = releasedHes + 20 msg = self.ppos_noconsensus_4.unDelegate(stakingBlockNum, self.nodeid_list2[2], delegate_value) assert msg["Status"] == False err_msg = "withdrewDelegate err: The von of delegate is not enough" assert err_msg in msg["ErrMsg"] @allure.title("赎回全部委托的金额与赎回金额为0") @pytest.mark.P1 def test_unDelegate_all(self): """ 验证 赎回全部委托的金额 验证 赎回金额为0 """ log.info("转账到钱包1") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[0]) log.info("转账到钱包2") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[1]) log.info("节点1质押成为验证人") self.ppos_noconsensus_1.createStaking(0, self.account_list[0], self.nodeid_list2[0], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) msg = self.ppos_noconsensus_1.getCandidateInfo(self.nodeid_list2[0]) stakingBlockNum = msg["Data"]["StakingBlockNum"] log.info("查询节点质押信息,质押块高{}".format(stakingBlockNum)) log.info("钱包2进行委托") value = 80 self.ppos_noconsensus_2.delegate(0, self.nodeid_list2[0], value) msg = self.ppos_noconsensus_2.getDelegateInfo(stakingBlockNum, self.account_list[1], self.nodeid_list2[0]) data = msg["Data"] """不清楚msg["Data"]对应value是str类型,需要再转字典""" data = json.loads(data) log.info(data) releasedHes = data["ReleasedHes"] releasedHes = Web3.fromWei(releasedHes, 'ether') log.info("委托钱包可赎回的金额单位eth:{}".format(releasedHes)) account_before = self.eth.getBalance(self.account_list[1]) msg = self.ppos_noconsensus_2.unDelegate(stakingBlockNum, self.nodeid_list2[0], releasedHes) assert msg["Status"] == True account_after = self.eth.getBalance(self.account_list[1]) result_value = account_after - account_before ##为什么会赎回多那么多钱?1000000000000159999910972325109760 assert account_before + data["ReleasedHes"] > account_after assert 70 < Web3.fromWei(result_value, "ether") < releasedHes, "赎回的金额减去gas应在这范围" log.info("全部委托金额赎回后,查询委托金额".format(account_after)) msg = self.ppos_noconsensus_2.getDelegateInfo(stakingBlockNum, self.account_list[1], self.nodeid_list2[0]) log.info(msg) """如果全部金额赎回,再查getDelegateInfo返回数据为空""" assert msg["Status"] == False assert msg["ErrMsg"] == "Delegate info is not found" @allure.title("多次委托,多次赎回") @pytest.mark.P1 def test_multiple_delegate_undelegate(self): """ 验证多次委托,多次赎回 """ log.info("转账到钱包5") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[4]) log.info("转账到钱包6") self.transaction(self.w3_list[0], self.address, to_address=self.account_list[5]) msg = self.ppos_noconsensus_5.getCandidateInfo(self.nodeid_list2[4]) if msg['Data'] == "": log.info("质押节点5成为验证节点") self.ppos_noconsensus_5.createStaking(0, self.account_list[4], self.nodeid_list2[4], self.externalId, self.nodeName, self.website, self.details, self.amount, self.programVersion) msg = self.ppos_noconsensus_5.getCandidateInfo(self.nodeid_list2[4]) stakingBlockNum = msg["Data"]["StakingBlockNum"] log.info("查询节点质押信息回去质押块高{}".format(stakingBlockNum)) value_list = [10, 11, 12, 13, 14, 15, 16, 17, 18] for value in value_list: log.info("钱包6 委托金额{}".format(value)) self.ppos_noconsensus_6.delegate(0, self.nodeid_list2[4], value) msg = self.ppos_noconsensus_6.getDelegateInfo(stakingBlockNum, self.account_list[5], self.nodeid_list2[4]) log.info(msg) data = json.loads(msg["Data"]) releasedHes = Web3.fromWei(data["ReleasedHes"], 'ether') log.info("查询委托的金额{}eth".format(releasedHes)) delegate_value = 0 for i in value_list: delegate_value = i + delegate_value assert delegate_value == releasedHes, "委托的金额与查询到的金额不一致" for value in value_list: log.info("赎回的金额:{}eth".format(value)) log.info("钱包6进行赎回") self.ppos_noconsensus_6.unDelegate(stakingBlockNum, self.nodeid_list2[4], value) log.info("赎回委托金额后查询委托信息") msg = self.ppos_noconsensus_6.getDelegateInfo(stakingBlockNum, self.account_list[5], self.nodeid_list2[4]) """如果全部金额赎回,再查getDelegateInfo返回数据为空""" log.info(msg)