def start_all_node(self, node_yml, genesis_file=None, static_node_file=None, is_need_init=True, genesis_path=conf.GENESIS_TMP, clean=False): """ 根据节点配置文件,启动节点 :param node_yml: 节点配置文件 :param genesis_file: genesis.json文件路径,is_need_init=True时且genesis_file为空时,会根据共识节点列表生成 :param static_node_file: 共识节点互连文件,为空时会根据共识节点生成 :param is_need_init: 是否需要初始化,初始化会删除原platon部署目录的所有数据 :param genesis_path: 新生成的genesis.json保存路径 :param clean: 是否删除platon部署目录的数据,is_need_init=True时,该参数无效 :return: """ self.check_node_yml(node_yml) collusion_list, nocollusion_list = get_node_list(node_yml) self.start_of_list(collusion_list, nocollusion_list, genesis_file=genesis_file, static_node_file=static_node_file, is_need_init=is_need_init, genesis_path=genesis_path, clean=clean)
def check_node_yml(self, node_yml): """ 校验配置文件,补充必要的字段 :param node_yml:节点配置文件路径 :return: - host: 10.10.8.237 port: 16789 rpcport: 6789 username: juzhen password: Platon123! id: 0afbd5564f886966493c2f4efb25d...df67474ff3bd6ce nodekey: 0b304c9e039b62269be...1adef94e8e114d7d url: http://10.10.8.237:6789 """ collusion_list, nocollusion_list = get_node_list(node_yml) result = {} result_collusion_list = [] result_nocollusion_list = [] update = 0 if len(collusion_list) >= 1: for nodedict in collusion_list: nodedict, update = self.handle_nodedict(nodedict, update) result_collusion_list.append(nodedict) result["collusion"] = result_collusion_list if len(nocollusion_list) >= 1: for nodedict in nocollusion_list: nodedict, update = self.handle_nodedict(nodedict, update) result_nocollusion_list.append(nodedict) result["nocollusion"] = result_nocollusion_list if update == 1: with open(node_yml, encoding="utf-8", mode="w") as f: yaml.dump(result, f, Dumper=yaml.RoundTripDumper)
def booms(self, node_yaml): """ 根据节点配置文件,关闭节点机器所有platon进程,关闭后节点无法重启 :param node_yaml: 节点配置文件路径 :return: """ collusion_list, nocollusion_list = get_node_list(node_yaml) node_list = collusion_list + nocollusion_list self.booms_of_list(node_list)
def kill_of_yaml(self, node_yaml): """ 根据节点配置文件,以kill方式关闭节点,关闭后,节点还能被重启 :param node_yaml: 节点配置文件路径 :return: """ collusion_list, nocollusion_list = get_node_list(node_yaml) node_list = collusion_list + nocollusion_list self.kill_of_list(node_list)
def stop_of_yml(self, node_yml: str): """ 根据配置文件,关闭节点,关闭后节点无法重启,只能重新部署链 :param node_yml: 节点配置文件路径 :return: """ collusion_list, nocollusion_list = get_node_list(node_yml) node_list = collusion_list + nocollusion_list self.stop_of_list(node_list)
def setup_class(self): self.auto.start_all_node(self.node_yml, genesis_file=conf.GENESIS_TMP, static_node_file=conf.STATIC_NODE_FILE) # 等一下,同步块高 collusion, _ = get_node_list(conf.NODE_YML) collusion_w3 = connect_web3(collusion[0]["url"]) collusion_block = collusion_w3.eth.blockNumber _, nocollusion = get_node_list(self.node_yml) self.url = nocollusion[0]['url'] self.ip = nocollusion[0]["host"] self.wt = PlatonContractTransaction(self.url) self.password = conf.PASSWORD nocollusion_block = self.wt.eth.blockNumber if collusion_block - nocollusion_block >= 100: time.sleep(20) elif 100 > collusion_block - nocollusion_block >= 50: time.sleep(10) else: time.sleep(5) addrress = self.wt.w3.toChecksumAddress(conf.ADDRESS) self.wt.w3.personal.unlockAccount(addrress, self.password, 999999) """部署合约""" resp = self.wt.contract_deploy( get_byte_code(abspath('./data/contract/vccMain.wasm')), get_abi_bytes(abspath(r'./data/contract/vccMain.cpp.abi.json')), addrress) result = self.wt.eth.waitForTransactionReceipt(resp) self.contract_address = result['contractAddress'] log.info(self.contract_address) if len(self.wt.eth.getCode(self.contract_address)) < 10: raise Exception("合约部署失败") node = nocollusion[0] ssh, sftp, t = connect_linux(node['host'], username=node['username'], password=node['password']) pwd_list = run_ssh(ssh, "pwd") pwd = pwd_list[0].strip("\r\n") account = 'UTC--2018-10-04T09-02-39.439063439Z--493301712671ada506ba6ca7891f436d29185821' self.wallet_path = '{}/{}/data16789/keystore/{}'.format( pwd, conf.DEPLOY_PATH, account) cmd = '''nohup java -jar ./vc_tool/vctool-1.0.jar > ./vc_tool/nohup.out 2>&1 &''' run_ssh(ssh, cmd) self.get_url = 'http://{}:8112/test/getResult'.format(self.ip)
def deploy_default_yml(self, node_yml): """ 根据节点配置文件,使用默认参数部署节点 :param node_yml: 节点配置文件 :return: """ self.check_node_yml(node_yml) collusion_list, nocollusion_list = get_node_list(node_yml) node_list = collusion_list + nocollusion_list self.deploy_default_list(node_list)
def update_node_yml(self, node_yml): """ 根据节点配置文件,更新节点 :param node_yml: 节点配置文件 :return: """ self.check_node_yml(node_yml) collusion_list, nocollusion_list = get_node_list(node_yml) node_list = collusion_list + nocollusion_list self.update_node_list(node_list)
def restart_yml(self, node_yml): """ 根据配置文件重启节点 :param node_yml: 节点配置文件 :return: """ self.check_node_yml(node_yml) collusion_list, nocollusion_list = get_node_list(node_yml) node_list = collusion_list + nocollusion_list self.restart_list(node_list)
def test_platon_versions(self): collusion_list, _ = get_node_list(self.node_yml) node = collusion_list[0] ssh, sftp, t = connect_linux(node['host'], username=node['username'], password=node['password']) cmd_list = run_ssh( ssh, "{}/node-{}/platon version".format(conf.DEPLOY_PATH, node["port"])) versions = conf.VERSION assert versions in cmd_list[1], "版本号不正确"
def deploy_contract(self): consensus_list, _ = get_node_list(self.node_yml) url = consensus_list[0]['url'] wt = PlatonContractTransaction(url) addrress = wt.w3.toChecksumAddress(conf.ADDRESS) wt.w3.personal.unlockAccount(addrress, conf.PASSWORD, 99999999) log.info("部署合约") resp = wt.contract_deploy( get_byte_code(abspath('./data/contract/sum.wasm')), get_abi_bytes(abspath('./data/contract/sum.cpp.abi.json')), addrress) log.info("获取合约交易信息") result = wt.eth.waitForTransactionReceipt(resp) contract_address = result['contractAddress'] contract_number = result['blockNumber'] return contract_address, resp, contract_number
def test_punishment_income(self): ''' 验证低出块率验证节点的处罚金自动转账到激励池 :return: ''' #随机获取其中一个正在出块的节点信息 node_info = get_node_list(conf.TWENTY_FIVENODE_YML) node_info_length = len(node_info) - 1 index = random.randint(0, node_info_length) node_data = node_info[0][index] print(node_data) platon_ppos = Ppos('http://10.10.8.157:6789', self.address, chainid=102, privatekey=conf.PRIVATE_KEY) # platon_ppos = self.ppos_link () incentive_pool_balance_befor = platon_ppos.eth.getBalance( conf.INCENTIVEPOOLADDRESS) log.info('处罚之前激励池查询余额:{}'.format(incentive_pool_balance_befor)) #停止其中一个正在出块的节点信息 try: self.auto = AutoDeployPlaton(cbft=self.cbft_json_path) self.auto.kill(node_data) platon_ppos = self.ppos_link(node_data['url']) if not platon_ppos.web3.isConnected(): platon_ppos = self.ppos_link() current_block = platon_ppos.eth.blockNumber() waiting_time = 250 - (current_block % 250) time.sleep(waiting_time + 1) incentive_pool_balance_after = platon_ppos.eth.getBalance( conf.INCENTIVEPOOLADDRESS) log.info('处罚之后激励池查询余额:{}'.format(incentive_pool_balance_after)) punishment_CandidateInfo = platon_ppos.getCandidateInfo( node_data['id']) if punishment_CandidateInfo['Status'] == 'True': punishment_amount = punishment_CandidateInfo['Data'][ 'Shares'] * (20 / 100) assert incentive_pool_balance_after == incentive_pool_balance_befor + punishment_amount else: log.info("查询处罚节点:{}质押信息失败".format(node_data['host'])) else: log.info("当前质押节点:{}链接正常".format(node_data['host'])) except: status = 1 assert status == 0, '停止节点:{}失败'.format(node_data['host'])
def test_punishment_income(self): ''' 验证低出块率验证节点的处罚金自动转账到激励池 :return: ''' url = CommonMethod.link_list(self) platon_ppos = Ppos(url, self.address, self.chainid) incentive_pool_balance_befor = platon_ppos.eth.getBalance( conf.INCENTIVEPOOLADDRESS) log.info('处罚之前激励池查询余额:{}'.format(incentive_pool_balance_befor)) #获取节点内置质押节点信息 nodeId = CommonMethod.read_out_nodeId(self, 'collusion') log.info("节点ID:{}".format(nodeId)) con_node, no_node = get_node_list(self.node_yml_path) nodes = con_node + no_node for node in nodes: if nodeId in node.values(): node_data = node #获取节点质押金额 punishment_CandidateInfo = platon_ppos.getCandidateInfo(nodeId) assert punishment_CandidateInfo['Status'] == True, "查询锁仓信息失败" pledge_amount1 = punishment_CandidateInfo['Data']['Released'] log.info("质押节点质押金:{}".format(pledge_amount1)) # 停止其中一个正在出块的节点信息 self.auto = AutoDeployPlaton() self.auto.kill(node_data) platon_ppos1 = connect_web3(node_data['url']) assert not platon_ppos1.isConnected(), "节点:{} 连接异常".format( node_data['host']) CommonMethod.get_next_settlement_interval(self) punishment_CandidateInfo = platon_ppos.getCandidateInfo(nodeId) pledge_amount3 = punishment_CandidateInfo['Data']['Released'] log.info("节点低出块率后节点质押金:{}".format(pledge_amount3)) incentive_pool_balance_after = platon_ppos.eth.getBalance( conf.INCENTIVEPOOLADDRESS) log.info('处罚之后激励池查询余额:{}'.format(incentive_pool_balance_after)) assert incentive_pool_balance_after == incentive_pool_balance_befor + ( pledge_amount1 - pledge_amount3)
def test_testnet(self): """ 测试testnet连接 :return: """ if conf.IS_TEST_NET: auto = AutoDeployPlaton(net_type="testnet") auto.start_all_node(conf.TEST_NET_NODE, is_need_init=False, clean=True) collusion, nocollusion = get_node_list(conf.TEST_NET_NODE) time.sleep(10) block_list = [] net_list = [] for nodedict in collusion: url = nodedict["url"] w3 = connect_web3(url) block_list.append(w3.eth.blockNumber) net_list.append(w3.net.peerCount) log.info(block_list, net_list) assert min(block_list) > 0, "区块没有增长" for net in net_list: assert net >= len(collusion) - \ 1, "共识节点连接节点数少于{}个".format(len(collusion) - 1) nocollusion_block_list = [] nocollusion_net_list = [] if max(block_list) < 250: time.sleep(250 - max(block_list) + 10) for nodedict in nocollusion: url = nodedict["url"] w3 = connect_web3(url) nocollusion_block_list.append(w3.eth.blockNumber) nocollusion_net_list.append(w3.net.peerCount) log.info(nocollusion_block_list, nocollusion_net_list) assert min(nocollusion_block_list) > 0, "区块没有增长" for net in nocollusion_net_list: assert net >= 1, "非共识节点没有连上测试网" else: pass
def monitor(node_yml): auto = AutoDeployPlaton() collusion, nocollusion = get_node_list(node_yml) node_list = collusion + nocollusion old_block = [0 * i for i in range(len(collusion))] t = 0 while True: time.sleep(120) t += 120 block_list = [] url_list = [] for node in node_list: try: w3 = connect_web3(node["url"]) if not w3.isConnected(): raise Exception("有节点被关闭了") block = w3.eth.blockNumber block_list.append(block) url_list.append(node["url"]) except: close_msg = "节点:{}:{}无法连接\n".format(node["host"], node["port"]) log.warning(close_msg) msg = build_msg(url_list, block_list, old_block) if max(block_list) - min(block_list) >= 100: log.error("区块差距过大") auto.kill_of_yaml(node_yml) send_to_gap(block_list, msg, node_yml) if max(block_list) - min(old_block) == 0: log.error("不出块了") auto.kill_of_yaml(node_yml) send_to_block(msg, node_yml) if t >= 21600: t = 0 send_email(EmailInfo, msg) old_block = block_list
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 TestContract: node_yml = conf.NODE_YML collusion_list, nocollusion_list = get_node_list(node_yml) nocollusion_url = nocollusion_list[0]['url'] collusion_url = collusion_list[0]['url'] address = Web3.toChecksumAddress(conf.ADDRESS) private_key_hex = conf.PRIVATE_KEY private_key = HexBytes(private_key_hex) url_list = [nocollusion_url, collusion_url] param_list = [(abspath('./data/contract/Fibonacci.wasm'), abspath('./data/contract/Fibonacci.cpp.abi.json'), 10, 143), (abspath('./data/contract/matmul.wasm'), abspath('./data/contract/matmul.cpp.abi.json'), 10, -183325)] @allure.title("非共识节点&共识节点 部署wasm合约测试") @pytest.mark.parametrize('pt1', url_list) def test_consensus_and_deconsensus_contract_deploy(self, pt1): ''' 非共识节点&共识节点 部署wasm合约测试 ''' pt = PlatonContractTransaction(pt1) wasm_path = abspath('./data/contract/sum.wasm') abi_path = abspath('./data/contract/sum.cpp.abi.json') # 部署合约 contract_address = contract_deploy(pt, wasm_path, abi_path) assert contract_address is not None, '合约部署失败,合约地址为空' contract_code = pt.eth.getCode(contract_address) assert len(contract_code) > 3, '合约部署异常,getCode(contract_address)结果异常' @allure.title("非共识节点&共识节点 wasm合约交易、event事件、call方法测试") @pytest.mark.parametrize('pt1', url_list) def test_consensus_and_deconsensus_contract_transaction(self, pt1): ''' 非共识节点&共识节点 wasm合约交易、event事件、call方法测试 ''' pt = PlatonContractTransaction(pt1) wasm_path = abspath('./data/contract/sum.wasm') abi_path = abspath('./data/contract/sum.cpp.abi.json') address = pt.eth.coinbase contract_address = contract_deploy(pt, wasm_path, abi_path) # 发送合约交易 data_list = [encoder.encode_type( 2), encoder.encode_string('set')] trans_hex = pt.contract_transaction( address, contract_address, data_list) try: result = pt.eth.waitForTransactionReceipt(trans_hex) except: assert False, "等待超时,交易哈希:{}".format(trans_hex) # 解析event事件 topics = result['logs'][0]['topics'] data = result['logs'][0]['data'] event = Event(json.load(open(abi_path))) event_data = event.event_data(topics, data) assert 'set success' in event_data['create'][0], '合约交易失败,event事件无"set success"' # call方法查询交易结果 data_list_for_call = [encoder.encode_type( 2), encoder.encode_string('get')] receive = pt.contract_call( address, contract_address, data_list_for_call) decoded_sum_result = int.from_bytes(receive, 'big') assert decoded_sum_result == 1, '自增失败,预期自增后结果为1,实际值为{}'.format( decoded_sum_result) @allure.title("非共识节点&共识节点 wasm合约输入、输出结果校验") @pytest.mark.parametrize('pt1', url_list) def test_consensus_and_deconsensus_contract_set_and_get_function(self, pt1): ''' 非共识节点&共识节点 wasm合约输入、输出结果校验 ''' pt = PlatonContractTransaction(pt1) wasm_path = abspath('./data/contract/inputtest.wasm') abi_path = abspath( './data/contract/inputtest.cpp.abi.json') address = pt.eth.coinbase contract_address = contract_deploy(pt, wasm_path, abi_path) set_value = -100 # 合约set方法存入int型数值 data_list = [encoder.encode_type(2), encoder.encode_string('set'), encoder.encode_int('int64', set_value)] trans_hex = pt.contract_transaction( address, contract_address, data_list) try: result = pt.eth.waitForTransactionReceipt(trans_hex) except: assert False, "等待超时,交易哈希:{}".format(trans_hex) # 合约get方法获取存入的数值校验是否一致 data_list_for_call = [encoder.encode_type( 2), encoder.encode_string('get')] receive = pt.contract_call( address, contract_address, data_list_for_call) get_value = contract_call_result_decode(receive) assert get_value == set_value, 'get结果异常,预期值:{},实际结果:{}'.format( set_value, get_value) def _singed_contract_deploy(self, pt, wasm_path, abi_path): ''' 部署wasm签名合约方法 ''' deploy_trans_hash = pt.signed_contract_deploy(get_byte_code(wasm_path), get_abi_bytes( abi_path), self.address, self.private_key) try: result = pt.eth.waitForTransactionReceipt(deploy_trans_hash) except: assert False, "等待超时,交易哈希:{}".format(deploy_trans_hash) contract_address = result['contractAddress'] assert len(pt.eth.getCode(contract_address) ) > 3, '合约部署异常,getCode(contract_address)结果异常' return contract_address @allure.title("非共识节点&共识节点 部署wasm签名合约测试") @pytest.mark.parametrize('pt1', url_list) def test_consensus_and_deconsensus_singed_contract_deploy(self, pt1): ''' 非共识节点&共识节点 部署wasm签名合约测试 ''' pt = PlatonContractTransaction(pt1) wasm_path = abspath('./data/contract/sum.wasm') abi_path = abspath('./data/contract/sum.cpp.abi.json') # 部署合约 contract_address = self._singed_contract_deploy( pt, wasm_path, abi_path) assert contract_address is not None, '合约部署失败,合约地址为空' contract_code = pt.eth.getCode(contract_address) assert len(contract_code) > 3, '合约部署异常,getCode(contract_address)结果异常' @allure.title("非共识节点&共识节点 wasm合约签名交易、event事件、call方法测试") @pytest.mark.parametrize('pt1', url_list) def test_consensus_and_deconsensus_singed_contract_transaction(self, pt1): ''' 非共识节点&共识节点 wasm合约签名交易、event事件、call方法测试 ''' pt = PlatonContractTransaction(pt1) wasm_path = abspath('./data/contract/sum.wasm') abi_path = abspath('./data/contract/sum.cpp.abi.json') address = pt.eth.coinbase contract_address = self._singed_contract_deploy( pt, wasm_path, abi_path) # 发送合约交易 data_list = [encoder.encode_type( 2), encoder.encode_string('set')] trans_hex = pt.signed_contract_transaction( address, contract_address, data_list, self.private_key) try: result = pt.eth.waitForTransactionReceipt(trans_hex) except: assert False, "等待超时,交易哈希:{}".format(trans_hex) # 解析event事件 topics = result['logs'][0]['topics'] data = result['logs'][0]['data'] event = Event(json.load(open(abi_path))) event_data = event.event_data(topics, data) assert 'set success' in event_data['create'][0], '合约交易失败,event事件无"set success"' # call方法查询交易结果 data_list_for_call = [encoder.encode_type( 2), encoder.encode_string('get')] receive = pt.contract_call( address, contract_address, data_list_for_call) decoded_sum_result = int.from_bytes(receive, 'big') assert decoded_sum_result == 1, '自增失败,预期自增后结果为1,实际值为{}'.format( decoded_sum_result) @allure.title("非共识节点&共识节点 wasm签名合约输入、输出结果校验") @pytest.mark.parametrize('pt1', url_list) def test_consensus_and_deconsensus_signed_contract_set_and_get_function(self, pt1): ''' 非共识节点&共识节点 wasm签名合约输入、输出结果校验 ''' pt = PlatonContractTransaction(pt1) wasm_path = abspath('./data/contract/inputtest.wasm') abi_path = abspath( './data/contract/inputtest.cpp.abi.json') address = pt.eth.coinbase contract_address = self._singed_contract_deploy( pt, wasm_path, abi_path) set_value = -100 # 合约set方法存入int型数值 data_list = [encoder.encode_type(2), encoder.encode_string('set'), encoder.encode_int('int64', set_value)] trans_hex = pt.signed_contract_transaction( address, contract_address, data_list, self.private_key) result = '' for i in range(3): try: result = pt.eth.waitForTransactionReceipt(trans_hex) except: pt.reconnect() assert result != '', "等待超时,交易哈希:{}".format(trans_hex) # 合约get方法获取存入的数值校验是否一致 data_list_for_call = [encoder.encode_type( 2), encoder.encode_string('get')] receive = pt.contract_call( address, contract_address, data_list_for_call) get_value = contract_call_result_decode(receive) assert get_value == set_value, 'get结果异常,预期值:{},实际结果:{}'.format( set_value, get_value) time.sleep(1) @allure.title("各算法合约计算结果测试") @pytest.mark.parametrize('wasm_path,abi_path,set_value,expect_value', param_list) def test_calc_contracts(self, wasm_path, abi_path, set_value, expect_value): ''' 各算法合约计算结果测试 ''' pt_one = PlatonContractTransaction(self.nocollusion_url) address = pt_one.eth.coinbase contract_address = contract_deploy( pt_one, wasm_path, abi_path) # 合约set方法存入int型数值 data_list = [encoder.encode_type(2), encoder.encode_string('set'), encoder.encode_int('int64', set_value)] trans_hex = pt_one.contract_transaction( address, contract_address, data_list) try: result = pt_one.eth.waitForTransactionReceipt(trans_hex) except: assert False, "等待超时,交易哈希:{}".format(trans_hex) # 合约get方法获取存入的数值校验是否一致 data_list_for_call = [encoder.encode_type( 2), encoder.encode_string('get')] receive = pt_one.contract_call( address, contract_address, data_list_for_call) get_value = contract_call_result_decode(receive) assert get_value == expect_value, 'get结果异常,预期值:{},实际结果:{}'.format( expect_value, get_value)
class TestConsensus: node_yml = conf.NODE_YML consensus_list, _ = get_node_list(node_yml) f = get_f(consensus_list) n = len(consensus_list) url_list, enode_list, nodeid_list, ip_list, _ = get_node_info( node_yml)["collusion"] genesis_path = conf.GENESIS_TMP auto = AutoDeployPlaton() cbft_path = conf.CBFT_TMP cbft_template = conf.CBFT_TEMPLATE def teardown_class(self): self.auto.start_all_node(self.node_yml) def get_cbft_json_data(self, period, duration): with open(self.cbft_template, 'r', encoding='utf-8') as f: res = json.loads(f.read()) res['period'] = period res['duration'] = duration with open(self.cbft_path, 'w', encoding='utf-8') as b: cbft_json = json.dumps(res) b.write(cbft_json) @allure.title("每个节点在窗口期正常出块") def test_block_out_of_each_node_window(self): """ 用例id:73 测试 N 个节点每个窗口期都在出块 """ log.info("更新cbft文件") self.get_cbft_json_data(period=1, duration=10) auto = AutoDeployPlaton(cbft=self.cbft_path) auto.start_all_node(self.node_yml) log.info("跟所有节点建立连接") w3_list = [connect_web3(url) for url in self.url_list] w3 = w3_list[0] start_block = w3.eth.blockNumber time.sleep(self.n * 10 + 5) block_number = w3.eth.blockNumber if block_number > 0: log.info("正在出块,块高:{}".format(block_number)) node_id_dict = {} log.info("获取1至{}块的nodeID".format(block_number)) for block in range(start_block, block_number + 1): node_id = get_pub_key(self.url_list[0], block) if node_id not in node_id_dict.keys(): node_id_dict[node_id] = 1 else: node_id_dict[node_id] += 1 log.info("nodeID对应的出块数{}".format(node_id_dict)) assert self.n == len(node_id_dict), "出块节点数少于共识节点数" for k, v in node_id_dict.items(): assert 0 <= v <= 20, "节点{}出块周期约为10个块,实际为{}".format(k, v) @allure.title("cbft.json配置period{period}-{duration}") @pytest.mark.parametrize('period,duration', [(1, 10), (3, 30), (5, 50), (10, 100), (0, 10)]) def test_block_time_period(self, period, duration): ''' 用例id 1,2,3,4,5 测试period的不同值,观察查看时间 根据5种场景,分别出块时间约为1,3,5,10,1s ''' log.info("更新cbft.json") self.get_cbft_json_data(period, duration) auto = AutoDeployPlaton(cbft=self.cbft_path) auto.start_all_node(self.node_yml) time.sleep(duration + 5) log.info("跟所有节点建立连接") w3_list = [connect_web3(url) for url in self.url_list] w3 = w3_list[0] block_number = w3.eth.blockNumber assert block_number > 1, "没有正常出块" log.info(block_number) start_time = w3.eth.getBlock(1).get("timestamp") end_time = w3.eth.getBlock(block_number).get("timestamp") use_time = end_time - start_time average_time = int(use_time / (block_number - 1)) log.info("平均出块时间{}".format(average_time)) if period == 0: period = 1 deviation = int(period * 1000 * 0.5) assert period * 1000 - deviation < average_time < period * \ 1000 + deviation, "出块间隔过大或过小" @allure.title("cbft.json配置period{period}-{duration}-{delay_time}--{number}" ) @pytest.mark.parametrize('period,duration,delay_time,number', [(1, 10, 50, 30), (1, 20, 90, 70), (1, 30, 130, 90), (1, 50, 180, 140), (1, 100, 350, 250)]) def test_block_cycle_duration(self, period, duration, delay_time, number): ''' 用例id 6,7,8,9,10 测试duration的不同值,观察出块周期 根据5种场景,出块周期约为10,20,30,50,100 ''' self.get_cbft_json_data(period, duration) auto = AutoDeployPlaton(cbft=self.cbft_path) log.info("上传cbft文件成功") auto.start_all_node(self.node_yml) time.sleep(delay_time) log.info("跟所有节点建立连接") w3_list = [connect_web3(url) for url in self.url_list] w3 = w3_list[0] block_number = w3.eth.blockNumber if block_number > 0: log.info("正在出块,块高:{}".format(block_number)) if block_number < number: raise Exception("出块很慢,没达到预期{}".format(number)) node_id_dict = {} log.info("获取1至{}块的nodeID".format(number)) for block in range(1, number): node_id = get_pub_key(self.url_list[0], block) if node_id not in node_id_dict.keys(): node_id_dict[node_id] = [block] else: node_id_dict[node_id].append(block) log.info("获取到全部的nodeID对应的出块".format(node_id_dict)) log.info("由于第一组nodeID收集数据不全,从第二组开始收集统计,删除第一组") node_id_list = [] for node_id in node_id_dict.keys(): node_id_list.append(node_id) node_id_dict.pop(node_id_list[0]) log.info("统计出nodeID对应的出块ID{}".format(node_id_dict)) print(node_id_dict) print(node_id_list) if duration == 10: block_cycle_a = node_id_dict.get(node_id_list[1]) log.info("出块人A出块周期数:%s" % block_cycle_a) assert 7 <= len(block_cycle_a) <= 12, "出块周期预期在7到12,实际{}".format( len(block_cycle_a)) block_cycle_b = node_id_dict.get(node_id_list[2]) log.info("出块人B出块周期数:%s" % block_cycle_b) assert 7 <= len(block_cycle_b) <= 12, "出块周期预期在7到12,实际{}".format( len(block_cycle_b)) times_tamp_a = w3.eth.getBlock(block_cycle_a[-1]).get("timestamp") times_tamp_b = w3.eth.getBlock(block_cycle_b[-1]).get("timestamp") log.info("获取出块人B的最后一个块的时间戳%s" % times_tamp_b) assert 8000 < times_tamp_b - \ times_tamp_a < 12000, "预期出块周期为8到12s,实际为{}".format( times_tamp_b - times_tamp_a) log.info( "出块人B最后一个块出块时间-出块人A最后一个块出块时间 = 出块周期时间{}".format(times_tamp_b - times_tamp_a)) if duration == 20: block_cycle_a = node_id_dict.get(node_id_list[1]) log.info("出块人A出块周期数:%s" % block_cycle_a) assert 16 <= len(block_cycle_a) <= 23, "出块周期预期在16到23,实际{}".format( len(block_cycle_a)) block_cycle_b = node_id_dict.get(node_id_list[2]) log.info("出块人B出块周期数:%s" % block_cycle_b) assert 16 <= len(block_cycle_b) <= 23, "出块周期预期在16到23,实际{}".format( len(block_cycle_b)) times_tamp_a = w3.eth.getBlock(block_cycle_a[-1]).get("timestamp") times_tamp_b = w3.eth.getBlock(block_cycle_b[-1]).get("timestamp") log.info("获取出块人B的最后一个块的时间戳%s" % times_tamp_b) assert 16000 < times_tamp_b - times_tamp_a < 23000, "预期出块周期为16到23s,实际为{}".format( times_tamp_b - times_tamp_a) log.info( "出块人B最后一个块出块时间-出块人A最后一个块出块时间 = 出块周期时间{}".format(times_tamp_b - times_tamp_a)) if duration == 30: block_cycle_a = node_id_dict.get(node_id_list[1]) log.info("出块人A出块周期数:%s" % block_cycle_a) assert 26 <= len(block_cycle_a) <= 33, "出块周期预期在26到33,实际{}".format( len(block_cycle_a)) block_cycle_b = node_id_dict.get(node_id_list[2]) log.info("出块人B出块周期数:%s" % block_cycle_b) assert 26 <= len(block_cycle_b) <= 33, "出块周期预期在26到33,实际{}".format( len(block_cycle_b)) times_tamp_a = w3.eth.getBlock(block_cycle_a[-1]).get("timestamp") times_tamp_b = w3.eth.getBlock(block_cycle_b[-1]).get("timestamp") log.info("获取出块人B的最后一个块的时间戳%s" % times_tamp_b) assert 26000 < times_tamp_b - times_tamp_a < 33000, "预期出块周期为26到30s,实际为{}".format( times_tamp_b - times_tamp_a) log.info( "出块人B最后一个块出块时间-出块人A最后一个块出块时间 = 出块周期时间{}".format(times_tamp_b - times_tamp_a)) if duration == 50: block_cycle_a = node_id_dict.get(node_id_list[1]) log.info("出块人A出块周期数:%s" % block_cycle_a) assert 40 <= len(block_cycle_a) <= 60, "出块周期预期在40到60,实际{}".format( len(block_cycle_a)) block_cycle_b = node_id_dict.get(node_id_list[2]) log.info("出块人B出块周期数:%s" % block_cycle_b) assert 40 <= len(block_cycle_b) <= 60, "出块周期预期在40到60,实际{}".format( len(block_cycle_b)) times_tamp_a = w3.eth.getBlock(block_cycle_a[-1]).get("timestamp") times_tamp_b = w3.eth.getBlock(block_cycle_b[-1]).get("timestamp") log.info("获取出块人B的最后一个块的时间戳%s" % times_tamp_b) assert 4000 < times_tamp_b - times_tamp_a < 60000, "预期出块周期为40到60s,实际为{}".format( times_tamp_b - times_tamp_a) log.info( "出块人B最后一个块出块时间-出块人A最后一个块出块时间 = 出块周期时间{}".format(times_tamp_b - times_tamp_a)) if duration == 100: block_cycle_a = node_id_dict.get(node_id_list[1]) log.info("出块人A出块周期数:%s" % block_cycle_a) assert 90 <= len( block_cycle_a) <= 110, "出块周期预期在90到110,实际{}".format( len(block_cycle_a)) block_cycle_b = node_id_dict.get(node_id_list[2]) log.info("出块人B出块周期数:%s" % block_cycle_b) assert 90 <= len( block_cycle_b) <= 110, "出块周期预期在90到110,实际{}".format( len(block_cycle_b)) times_tamp_a = w3.eth.getBlock(block_cycle_a[-1]).get("timestamp") times_tamp_b = w3.eth.getBlock(block_cycle_b[-1]).get("timestamp") log.info("获取出块人B的最后一个块的时间戳%s" % times_tamp_b) assert 90000 < times_tamp_b - times_tamp_a < 110000, "预期出块周期为99到110s,实际为{}".format( times_tamp_b - times_tamp_a) log.info( "出块人B最后一个块出块时间-出块人A最后一个块出块时间 = 出块周期时间{}".format(times_tamp_b - times_tamp_a)) @allure.title("重启节点后查看旧块交易,钱包余额") def test_kill_process_observation_block_data(self): ''' 用例id 30,31,32,33 测试kill进程后,重启查看块高持续增长 测试kill进程后,重启查看旧块转账,合约信息不变 测试kill进程后,钱包余额不变 ''' log.info("部署节点") self.auto.start_all_node(self.node_yml) log.info("启动会等待60s出块") time.sleep(10) log.info("跟所有节点建立连接") w3_list = [connect_web3(url) for url in self.url_list] w3 = w3_list[0] number_before = w3.eth.blockNumber if number_before == 0: raise Exception("起服务但未出块") log.info("块高为:{}".format(number_before)) log.info("发起转账交易") t_hash = self.transaction(w3) result, number, result_block, hash_list = self.check_block_information( w3, t_hash) log.info("发起合约交易") contract_address, resp, contract_number = self.deploy_contract() log.info("kill 所有节点") self.auto.kill_of_yaml(self.node_yml) time.sleep(2) log.info("重启platon服务") self.auto.start_all_node(self.node_yml, is_need_init=False) log.info("重启25节点后,延迟30s") time.sleep(30) w3_list = [connect_web3(url) for url in self.url_list] w3 = w3_list[0] number_after = w3.eth.blockNumber assert number_after >= number_before, "块高未有增长" balance = w3.eth.getBalance(w3.eth.accounts[1]) assert balance == 100000, "kill进程重启后余额发生变化,余额为:{}".format(balance) log.info("查看重启前的{}区块转账信息".format(number)) t_hash_list = (w3.eth.getBlock(number).get("transactions")) log.info("查看重启前的{}区块合约信息".format(contract_number)) c_hash_list = (w3.eth.getBlock(contract_number).get("transactions")) log.info("通过transactions字段得到的交易哈希列表:{}".format(hash_list)) assert t_hash in t_hash_list, "kill进程重启后转账交易丢失" c_hash = HexBytes(resp) assert c_hash in c_hash_list, "kill进程重启后合约交易丢失" contract_address_after = w3.eth.waitForTransactionReceipt(resp).get( 'contractAddress') assert contract_address == contract_address_after, "kill进程后,合约地址发生改变" def check_block_information(self, w3, hash): transaction_hash = HexBytes(hash).hex() result = w3.eth.waitForTransactionReceipt(transaction_hash) number = result.get("blockNumber") result_block = w3.eth.getBlock(number) hash_list = result_block.get("transactions") return result, number, result_block, hash_list def transaction(self, w3, value=100000): from_address = w3.toChecksumAddress(w3.eth.accounts[0]) to_address = w3.toChecksumAddress(w3.personal.newAccount('88888888')) log.info("解锁账号") w3.personal.unlockAccount(from_address, '88888888', 666666) params = { 'to': to_address, 'from': from_address, 'gas': 91000000, 'gasPrice': 9000000000, 'value': value } t_hash = w3.eth.sendTransaction(params) return t_hash def deploy_contract(self): consensus_list, _ = get_node_list(self.node_yml) url = consensus_list[0]['url'] wt = PlatonContractTransaction(url) addrress = wt.w3.toChecksumAddress(conf.ADDRESS) wt.w3.personal.unlockAccount(addrress, conf.PASSWORD, 99999999) log.info("部署合约") resp = wt.contract_deploy( get_byte_code(abspath('./data/contract/sum.wasm')), get_abi_bytes(abspath('./data/contract/sum.cpp.abi.json')), addrress) log.info("获取合约交易信息") result = wt.eth.waitForTransactionReceipt(resp) contract_address = result['contractAddress'] contract_number = result['blockNumber'] return contract_address, resp, contract_number
from client_sdk_python import Web3 from common import log from common.abspath import abspath from common.handle_param import handle, handle_param from common.load_file import get_node_list from conf import setting as conf from data import basic as config_data from utils.platon_lib import contract from utils.platon_lib.contract import (PlatonContractTransaction, contract_call_result_decode) from utils.platon_lib.contract import encoder from utils.platon_lib.event import Event from utils.platon_lib.send_raw_transaction import send_raw_transaction collusion_list, _ = get_node_list(conf.NODE_YML) node_url = collusion_list[0]['url'] address = Web3.toChecksumAddress('493301712671ada506ba6ca7891f436d29185821') send_address = Web3.toChecksumAddress( "0xdB245C0ebbCa84395c98c3b2607863cA36ABBD79") send_privatekey = "b735b2d48e5f6e1dc897081f8655fdbb376ece5b2b648c55eee72c38102a0357" def contract_deploy(pt, wasm_path, abi_path): ''' 部署wasm合约方法 ''' address = pt.eth.coinbase pt.personal.unlockAccount(address, '88888888', 999999) deploy_trans_hash = pt.contract_deploy(contract.get_byte_code(wasm_path),
import time import allure import pytest from common import log from deploy.deploy import AutoDeployPlaton from common.connect import connect_web3 from conf import setting as conf from common.load_file import get_f, get_node_info, get_node_list node_yml = conf.NODE_YML collusion_list, _ = get_node_list(node_yml) f = int(get_f(collusion_list)) n = len(collusion_list) auto = AutoDeployPlaton() url_list, enode_list, nodeid_list, ip_list, _ = get_node_info( node_yml)["collusion"] genesis_file = conf.GENESIS_TMP static_node_file = conf.STATIC_NODE_FILE def teardown_function(): log.info("关闭所有节点") auto.kill_of_yaml(node_yml) def teardown_module(): auto.start_all_node(node_yml)
verfier_info_list = platon_dpos.GetVerifiersList() num = len(verfier_info_list) if num <= 1: f = 1 else: f = int((num - 1) / 3) + 1 stop_node_list = random.sample(node_list, random.randrange(1, f + 1)) q.put(1) log.info("重启节点:{}".format(stop_node_list)) auto.restart_list(stop_node_list) q.get() if __name__ == "__main__": node_yml = "./deploy/node/node_061.yml" node_list1, node_list2 = get_node_list(node_yml) node_list = node_list1 + node_list2 node_list_stop = copy.copy(node_list) w3 = PlatonDpos(node_list[0]["url"], web3.Web3().toChecksumAddress(conf.ADDRESS), conf.PASSWORD, abi=conf.DPOS_CONTRACT_ABI) th1 = threading.Thread(target=stop_node, args=(node_list_stop, w3)) th1.setDaemon(True) th1.start() th2 = threading.Thread(target=restart_node, args=(node_list, w3)) th2.setDaemon(True) th2.start() input("input q quit:") while q.empty(): exit()
def test_unlock_point_pledge_punish_amount(self): ''' 到达解锁期后处罚节点后锁仓账户的余额情况 :return: ''' nodeId = CommonMethod.get_no_candidate_list (self) log.info("质押节点ID:{}".format(nodeId)) url = CommonMethod.link_list (self) platon_ppos = Ppos (url, self.address, self.chainid) address1, private_key1 = CommonMethod.read_private_key_list () address2, private_key2 = CommonMethod.read_private_key_list () # 给发起锁仓账户转手续费 result = platon_ppos.send_raw_transaction ('', Web3.toChecksumAddress (self.address), Web3.toChecksumAddress (address1), self.base_gas_price, self.base_gas, self.value, self.privatekey) return_info = platon_ppos.eth.waitForTransactionReceipt (result) assert return_info is not None, "转账:{}失败".format (self.value) # 给发起质押账号转手续费 result = platon_ppos.send_raw_transaction ('', Web3.toChecksumAddress (self.address), Web3.toChecksumAddress (address2), self.base_gas_price, self.base_gas, self.value, self.privatekey) return_info = platon_ppos.eth.waitForTransactionReceipt (result) assert return_info is not None, "转账:{}失败".format (self.value) Balance = platon_ppos.eth.getBalance (address1) log.info ("{}账户余额:{}".format (address1, Balance)) Balance1 = platon_ppos.eth.getBalance (address1) log.info ("{}账号余额:{}".format (address2, Balance1)) # 创建锁仓计划 lockupamoutn = 900 loukupbalace = Web3.toWei (lockupamoutn, 'ether') plan = [{'Epoch': 3, 'Amount': loukupbalace}] result = platon_ppos.CreateRestrictingPlan (address2, plan, privatekey=private_key1, from_address=address1, gasPrice=self.base_gas_price, gas=self.staking_gas) assert result['Status'] == True, "创建锁仓计划返回的状态:{},用例失败".format (result['Status']) RestrictingInfo = platon_ppos.GetRestrictingInfo (address2) assert RestrictingInfo['Status'] == True, "查询锁仓计划返回的状态:{},用例失败".format (result['Status']) Balance2 = platon_ppos.eth.getBalance (address1) log.info ("{}发起锁仓后账户余额:{}".format (address1, Balance2)) # 申请质押节点 version = get_version (platon_ppos) amount = 900 result = platon_ppos.createStaking (1, address2, nodeId, 'externalId', 'nodeName', 'website', 'details', amount, version, privatekey=private_key2, from_address=address2, gasPrice=self.base_gas_price, gas=self.staking_gas) assert result['Status'] == True, "申请质押返回的状态:{},{},用例失败".format (result['Status'], result['ErrMsg']) platon_ppos.GetRestrictingInfo(address2) result = platon_ppos.getCandidateInfo(nodeId) assert result['Status'] == True, "获取质押节点返回状态为:{} 有误".format (result['Status']) RestrictingPlan = result['Data']['RestrictingPlanHes'] assert RestrictingPlan == Web3.toWei (amount, 'ether'),'质押金额:{} 有误'.format(RestrictingPlan) Balance3 = platon_ppos.eth.getBalance (address2) log.info ("{}质押完锁仓账户余额:{}".format (address2,Balance3)) #等待验证人加入共识出块节点 CommonMethod.get_next_settlement_interval (self,1) Balance4 = platon_ppos.eth.getBalance (address2) log.info ("{}加入共识验证人后账户余额:{}".format (address2, Balance4)) # 获取节点内置质押节点信息 con_node, no_node = get_node_list (self.node_yml_path) nodes = con_node + no_node for node in nodes: if nodeId in node.values (): node_data = node log.info("{}质押节点信息:{}".format(address2,node_data)) #停止质押节点 self.auto = AutoDeployPlaton () self.auto.kill (node_data) platon_ppos1 = connect_web3 (node_data['url']) assert not platon_ppos1.isConnected(),"节点:{} 连接异常".format(node_data['host']) # 到达解锁期后处罚节点后锁仓账户 CommonMethod.get_next_settlement_interval (self,1) Balance5 = platon_ppos.eth.getBalance (address2) log.info ("{}到达解锁期后处罚节点后预期账户余额:{}".format (address2,Balance4 + Web3.toWei (amount-(amount * 0.2), 'ether'))) log.info ("{}到达解锁期后处罚节点后实际账户余额:{}".format (address2,Balance5)) result = platon_ppos.getCandidateInfo(nodeId) assert Balance5 == Balance4 + Web3.toWei (amount-(amount * 0.2), 'ether'), "锁仓账户金额:{} 有误".format (Balance4) RestrictingInfo = platon_ppos.GetRestrictingInfo (address2) assert RestrictingInfo['Status'] == True, "获取锁仓计划返回状态为:{} 有误".format (result['Status']) dict_Info = json.loads (RestrictingInfo['Data']) assert dict_Info['balance'] == 0, "锁仓计划可用金额:{}有误".format (dict_Info['balance']) assert dict_Info['symbol'] == True, "欠释放状态:{} 有误".format (dict_Info['symbol']) assert dict_Info['debt'] == Web3.toWei (amount-(amount * 0.2), 'ether'), "欠释放锁仓金额:{} 有误".format (dict_Info['debt'])
@Description: 转账用例 ''' import time from hexbytes import HexBytes from client_sdk_python import Web3 from client_sdk_python.eth import Eth from common.connect import connect_web3 from common.load_file import get_node_list, get_f from conf import setting as conf from utils.platon_lib.send_raw_transaction import send_raw_transaction from deploy.deploy import generate_init_node node_yml = conf.NODE_YML collusion_list, nocollusion_list = get_node_list(node_yml) f = get_f(collusion_list) send_address = Web3.toChecksumAddress( "0xdB245C0ebbCa84395c98c3b2607863cA36ABBD79") send_privatekey = "b735b2d48e5f6e1dc897081f8655fdbb376ece5b2b648c55eee72c38102a0357" def setup_module(): collusion_list_p2p, _ = generate_init_node(collusion_list) for node in nocollusion_list: w3 = connect_web3(node["url"]) for p2p in collusion_list_p2p: w3.admin.addPeer(p2p) time.sleep(10)
def test_eliminated_verifier_create_lockup(self): ''' 验证人违规被剔除验证人列表,申请质押节点 :return: ''' nodeId = CommonMethod.get_no_candidate_list (self) url = CommonMethod.link_list (self) platon_ppos = Ppos (url, self.address, self.chainid) address1, private_key1 = CommonMethod.read_private_key_list () # 签名转账 result = platon_ppos.send_raw_transaction ('', Web3.toChecksumAddress (self.address), Web3.toChecksumAddress (address1), self.base_gas_price, self.base_gas, self.value, self.privatekey) return_info = platon_ppos.eth.waitForTransactionReceipt (result) assert return_info is not None, "转账:{}失败".format (self.value) balance = platon_ppos.eth.getBalance (address1) log.info ("{}发起锁仓账户余额:{}".format (address1,balance)) # 创建锁仓计划 lockupamoutn = 900 loukupbalace = Web3.toWei (lockupamoutn, 'ether') plan = [{'Epoch': 5, 'Amount': loukupbalace}] result = platon_ppos.CreateRestrictingPlan (address1, plan, privatekey=private_key1, from_address=address1, gasPrice=self.base_gas_price, gas=self.staking_gas) assert result['Status'] == True, "创建锁仓计划返回的状态:{},用例失败".format (result['Status']) RestrictingInfo = platon_ppos.GetRestrictingInfo (address1) assert RestrictingInfo['Status'] == True, "查询锁仓计划返回的状态:{},用例失败".format (result['Status']) # 申请质押节点 version = get_version (platon_ppos) amount = 200 result = platon_ppos.createStaking (1, address1, nodeId, 'externalId', 'nodeName', 'website', 'details', amount, version, privatekey=private_key1, from_address=address1, gasPrice=self.base_gas_price, gas=self.staking_gas) assert result['Status'] == True, "申请质押返回的状态:{},{},用例失败".format (result['Status'], result['ErrMsg']) result = platon_ppos.getCandidateInfo(nodeId) log.info("质押节点信息:{}".format(result)) # 等待成为共识验证人 CommonMethod.get_next_settlement_interval (self) CandidateInfo = platon_ppos.getCandidateInfo(nodeId) log.info("验证人信息{}".format(CandidateInfo)) VerifierList = platon_ppos.getVerifierList () log.info ("当前验证人列表:{}".format (VerifierList)) ValidatorList = platon_ppos.getValidatorList() log.info("当前共识验证人列表:{}".format(ValidatorList)) # for dictinfo in CandidateInfo['Data']: # if nodeId == dictinfo['NodeId']: # log.info("节点id:{}已成为共识验证人".format(nodeId)) # break # else: # log.info("节点id:{}未成为共识验证人".format(nodeId)) # status=0 # assert status == 1 # 获取节点内置质押节点信息 con_node, no_node = get_node_list (self.node_yml_path) nodes = con_node + no_node for node in nodes: if nodeId in node.values (): node_data = node # 停止其中一个正在出块的节点信息 self.auto = AutoDeployPlaton () self.auto.kill (node_data) platon_ppos1 = connect_web3 (node_data['url']) assert not platon_ppos1.isConnected (), "节点:{} 连接异常".format (node_data['host']) # 等待节点被剔除验证人列表 CommonMethod.get_next_consensus_wheel (self,2) # 申请质押节点 version = get_version (platon_ppos) amount = 200 result = platon_ppos.createStaking (1, address1, nodeId, 'externalId', 'nodeName', 'website', 'details', amount, version, privatekey=private_key1, from_address=address1, gasPrice=self.base_gas_price, gas=self.staking_gas) assert result['Status'] == False, "申请质押返回的状态:{},用例失败".format (result['Status'])
class TestBuildBlockChain: node_yml = conf.NODE_YML collusion_list, nocollusion_list = get_node_list(node_yml) one_collusion_url = nocollusion_list[0]["url"] data = get_node_info(node_yml) rpc_urls, enode_list, nodeid_list, _, _ = data["collusion"] w3_list = [connect_web3(url) for url in rpc_urls] genesis_file = conf.GENESIS_TMP auto = AutoDeployPlaton() def setup(self): self.auto.start_all_node(self.node_yml) def setup_class(self): self.w3_list = [connect_web3(url) for url in self.rpc_urls] def teardown_class(self): self.auto.start_all_node(self.node_yml) @allure.title("区块增长") def test_blocknumber_increase(self): ''' 测试块高是否正常增长 ''' for w3 in self.w3_list: for i in range(91): if w3.eth.blockNumber > 0: break time.sleep(1) if i == 90: raise Exception('区块不增长,块高:{}'.format(w3.eth.blockNumber)) # TODO: need fix python-sdk nonce bug # @allure.title("区块信息是否一致") # def test_block_synchronize(self): # ''' # 测试所有节点区块信息是否一致 # ''' # w3 = self.w3_list[0] # blocknumber = w3.eth.blockNumber # if blocknumber == 0: # time.sleep(15) # blocknumber = w3.eth.blockNumber # blockinfo = w3.eth.getBlock(blocknumber)['hash'] # for w in self.w3_list[1:-1]: # info = w.eth.getBlock(blocknumber)['hash'] # assert blockinfo == info, "不同节点的相同块高信息不一致区块号:{}".format( # blocknumber) # TODO: need fix python-sdk nonce bug # @allure.title("区块连续性,验证hash") # def test_hash_continuous(self): # """ # 测试区块的连续性,验证一定数量的区块,区块哈希必须是连续的 # """ # w3 = self.w3_list[0] # i = 0 # while True: # if w3.eth.blockNumber >= 100: # break # time.sleep(10) # i += 10 # if i >= 150: # assert False, "出块不正常" # block_hash = HexBytes(w3.eth.getBlock(1).get("hash")).hex() # for i in range(2, 100): # block = w3.eth.getBlock(i) # parent_hash = HexBytes(block.get("parentHash")).hex() # assert block_hash == parent_hash, "父区块哈希值错误" # block_hash = HexBytes(block.get("hash")).hex() @allure.title("不初始化启动节点和不同创世文件的节点互连") def test_no_init_no_join_chain(self): ''' 不初始化启动节点 ''' self.auto.start_of_list(self.nocollusion_list[0:1], is_need_init=False, clean=True) time.sleep(1) w3 = connect_web3(self.one_collusion_url) start_block = w3.eth.blockNumber time.sleep(10) end_block = w3.eth.blockNumber assert start_block == end_block, "区块高度增长了,开始块高{}-结束块高{}".format( start_block, end_block) w3.admin.addPeer(self.enode_list[0]) time.sleep(5) net_num = w3.net.peerCount assert net_num == 0, "连接节点数有增加" @allure.title("测试部署单节点私链") def test_build_one_node_privatechain(self): ''' 部署单节点私链 ''' auto = AutoDeployPlaton(genesis=conf.GENESIS_TEMPLATE2) auto.start_of_list(self.nocollusion_list[0:1], genesis_path=conf.GENESIS_TMP_OTHER) time.sleep(2) w3 = connect_web3(self.one_collusion_url) start_block = w3.eth.blockNumber log.info("start block number:{}".format(start_block)) time.sleep(10) end_block = w3.eth.blockNumber log.info("end block number:{}".format(end_block)) assert start_block < end_block, "区块高度没有增长" @allure.title("测试不同initnode创始文件之间节点互连") def test_init_diff_genesis_join_chain(self): ''' 使用不同genesis.json,addPeer ''' self.auto.start_of_list(self.nocollusion_list[0:1], genesis_path=conf.GENESIS_TMP_OTHER) time.sleep(2) net_num_1 = self.w3_list[0].net.peerCount w3 = connect_web3(self.one_collusion_url) w3.admin.addPeer(self.enode_list[0]) time.sleep(5) net_num_2 = self.w3_list[0].net.peerCount assert net_num_2 == net_num_1, "节点数有增加" peers = w3.net.peerCount log.info("加入其他链后,连接节点数{}".format(peers)) assert peers is 0, "peers节点数不为空" @allure.title("测试相同创始文件之间节点互连") def test_init_same_genesis_join_chain(self): ''' 测试相同的genesis.json节点加入addPeer ''' self.auto.start_of_list(self.nocollusion_list[0:1], genesis_file=self.genesis_file) time.sleep(2) w3 = connect_web3(self.one_collusion_url) w3.admin.addPeer(self.enode_list[0]) time.sleep(5) assert w3.net.peerCount > 0, "加入链失败" @allure.title("测试区块同步") def test_deconsensus_block_synchronize(self): ''' 非共识节点块高同步 ''' w3 = connect_web3(self.one_collusion_url) log.info(w3.net.peerCount) time.sleep(10) block_number = w3.eth.blockNumber assert block_number > 0, "非共识节点同步区块失败,块高:{}".format(block_number) @allure.title("测试fast模式同步") def test_syncmode(self): """ 同步 :return: """ auto = AutoDeployPlaton(syncmode="fast") auto.start_of_list(self.nocollusion_list[0:1], genesis_file=self.genesis_file) time.sleep(2) w3 = connect_web3(self.one_collusion_url) w3.admin.addPeer(self.enode_list[0]) time.sleep(5) collusion_w3 = self.w3_list[0] if collusion_w3.eth.blockNumber < 250: log.info("sleep,非共识节点需要229个块之后才会开始同步") time.sleep(250 - collusion_w3.eth.blockNumber) assert w3.net.peerCount > 0, "加入链失败" assert w3.eth.blockNumber >= 200, "区块同步失败,当前块高{}".format( w3.eth.blockNumber) # 目前没有测试网配置 # @allure.title("测试种子节点") # def test_testnet(self): # """ # 测试testnet连接 # :return: # """ # if conf.IS_TEST_NET: # auto = AutoDeployPlaton(net_type="testnet") # auto.start_all_node(conf.TEST_NET_NODE, # is_need_init=False, clean=True) # collusion, nocollusion = get_node_list(conf.TEST_NET_NODE) # time.sleep(10) # block_list = [] # net_list = [] # for nodedict in collusion: # url = nodedict["url"] # w3 = connect_web3(url) # block_list.append(w3.eth.blockNumber) # net_list.append(w3.net.peerCount) # log.info(block_list, net_list) # assert min(block_list) > 0, "区块没有增长" # for net in net_list: # assert net >= len(collusion) - \ # 1, "共识节点连接节点数少于{}个".format(len(collusion) - 1) # nocollusion_block_list = [] # nocollusion_net_list = [] # if max(block_list) < 250: # time.sleep(250 - max(block_list) + 10) # for nodedict in nocollusion: # url = nodedict["url"] # w3 = connect_web3(url) # nocollusion_block_list.append(w3.eth.blockNumber) # nocollusion_net_list.append(w3.net.peerCount) # log.info(nocollusion_block_list, nocollusion_net_list) # assert min(nocollusion_block_list) > 0, "区块没有增长" # for net in nocollusion_net_list: # assert net >= 1, "非共识节点没有连上测试网" # else: # pass @allure.title("测试platon文件的版本号") def test_platon_versions(self): collusion_list, _ = get_node_list(self.node_yml) node = collusion_list[0] ssh, sftp, t = connect_linux(node['host'], username=node['username'], password=node['password']) cmd_list = run_ssh( ssh, "{}/node-{}/platon version".format(conf.DEPLOY_PATH, node["port"])) versions = conf.VERSION assert versions in cmd_list[1], "版本号不正确" @allure.title("测试重启所有共识节点") def test_restart_all(self): current_block = self.w3_list[0].eth.blockNumber log.info("重启前块高:{}".format(current_block)) self.auto.restart_list(self.collusion_list) log.info("重启所有共识节点成功") time.sleep(30) after_block = self.w3_list[0].eth.blockNumber log.info("重启后块高为:{}".format(after_block)) assert after_block - current_block >= 10, "重启后区块没有正常增长"