def main(): node_root = "/tmp/near/upgradable" if os.path.exists(node_root): shutil.rmtree(node_root) subprocess.check_output('mkdir -p /tmp/near', shell=True) near_root, (stable_branch, current_branch) = branches.prepare_ab_test("beta") # Setup local network. print([ "%snear-%s" % (near_root, stable_branch), "--home=%s" % node_root, "testnet", "--v", "4", "--prefix", "test" ]) subprocess.call([ "%snear-%s" % (near_root, stable_branch), "--home=%s" % node_root, "testnet", "--v", "4", "--prefix", "test" ]) genesis_config_changes = [("epoch_length", 20), ("num_block_producer_seats", 10), ("num_block_producer_seats_per_shard", [10]), ("block_producer_kickout_threshold", 80), ("chunk_producer_kickout_threshold", 80)] node_dirs = [os.path.join(node_root, 'test%d' % i) for i in range(4)] for i, node_dir in enumerate(node_dirs): cluster.apply_genesis_changes(node_dir, genesis_config_changes) # Start 3 stable nodes and one current node. config = { "local": True, 'near_root': near_root, 'binary_name': "near-%s" % stable_branch } nodes = [ cluster.spin_up_node(config, near_root, node_dirs[0], 0, None, None) ] for i in range(1, 3): nodes.append( cluster.spin_up_node(config, near_root, node_dirs[i], i, nodes[0].node_key.pk, nodes[0].addr())) config["binary_name"] = "near-%s" % current_branch nodes.append( cluster.spin_up_node(config, near_root, node_dirs[3], 3, nodes[0].node_key.pk, nodes[0].addr())) wait_for_blocks_or_timeout(nodes[0], 20, 120) # Restart stable nodes into new version. for i in range(3): nodes[i].kill() nodes[i].binary_name = config['binary_name'] nodes[i].start(nodes[0].node_key.pk, nodes[0].addr()) wait_for_blocks_or_timeout(nodes[3], 60, 120) status0 = nodes[0].get_status() status3 = nodes[3].get_status() protocol_version = status0['protocol_version'] latest_protocol_version = status3["latest_protocol_version"] assert protocol_version == latest_protocol_version,\ "Latest protocol version %d should match active protocol version %d" % (latest_protocol_version, protocol_version)
def main(): node_root = "/tmp/near/upgradable" if os.path.exists(node_root): shutil.rmtree(node_root) subprocess.check_output('mkdir -p /tmp/near', shell=True) # TODO(#3285): use proper branch near_root, (stable_branch, current_branch) = branches.prepare_ab_test("1.13.0") # Setup local network. print([ "%snear-%s" % (near_root, stable_branch), "--home=%s" % node_root, "testnet", "--v", "4", "--prefix", "test" ]) subprocess.call([ "%snear-%s" % (near_root, stable_branch), "--home=%s" % node_root, "testnet", "--v", "4", "--prefix", "test" ]) genesis_config_changes = [ ("epoch_length", 20), ("num_block_producer_seats", 10), ("num_block_producer_seats_per_shard", [10]), ("block_producer_kickout_threshold", 80), ("chunk_producer_kickout_threshold", 80), ("chain_id", "testnet") ] node_dirs = [os.path.join(node_root, 'test%d' % i) for i in range(4)] for i, node_dir in enumerate(node_dirs): cluster.apply_genesis_changes(node_dir, genesis_config_changes) # Start 3 stable nodes and one current node. config = { "local": True, 'near_root': near_root, 'binary_name': "near-%s" % stable_branch } nodes = [cluster.spin_up_node( config, near_root, node_dirs[0], 0, None, None)] for i in range(1, 3): nodes.append(cluster.spin_up_node( config, near_root, node_dirs[i], i, nodes[0].node_key.pk, nodes[0].addr())) config["binary_name"] = "near-%s" % current_branch nodes.append(cluster.spin_up_node( config, near_root, node_dirs[3], 3, nodes[0].node_key.pk, nodes[0].addr())) time.sleep(2) # deploy a contract status = nodes[0].get_status() hash = status['sync_info']['latest_block_hash'] tx = sign_deploy_contract_tx( nodes[0].signer_key, load_binary_file( '../runtime/near-vm-runner/tests/res/test_contract_rs.wasm'), 1, base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) assert 'error' not in res, res # write some random value tx = sign_function_call_tx(nodes[0].signer_key, nodes[0].signer_key.account_id, 'write_random_value', [], 10**13, 0, 2, base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res # hex_account_id = (b"I'm hex!" * 4).hex() hex_account_id = '49276d206865782149276d206865782149276d206865782149276d2068657821' tx = sign_payment_tx(key=nodes[0].signer_key, to=hex_account_id, amount=10 ** 25, nonce=3, blockHash=base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) # Account doesn't exist assert 'error' not in res, res assert 'Failure' in res['result']['status'], res # No account res = nodes[0].get_account(hex_account_id) assert 'error' in res, res wait_for_blocks_or_timeout(nodes[0], 20, 120) # Restart stable nodes into new version. for i in range(3): nodes[i].kill() nodes[i].binary_name = config['binary_name'] nodes[i].start(nodes[0].node_key.pk, nodes[0].addr()) wait_for_blocks_or_timeout(nodes[3], 60, 120) status0 = nodes[0].get_status() status3 = nodes[3].get_status() protocol_version = status0['protocol_version'] latest_protocol_version = status3["latest_protocol_version"] assert protocol_version == latest_protocol_version, \ "Latest protocol version %d should match active protocol version %d" % (latest_protocol_version, protocol_version) hash = status0['sync_info']['latest_block_hash'] # write some random value again tx = sign_function_call_tx(nodes[0].signer_key, nodes[0].signer_key.account_id, 'write_random_value', [], 10**13, 0, 4, base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res tx = sign_payment_tx(key=nodes[0].signer_key, to=hex_account_id, amount=10 ** 25, nonce=5, blockHash=base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) # Successfully created a new account on transfer to hex assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res hex_account_balance = int(nodes[0].get_account(hex_account_id)['result']['amount']) assert hex_account_balance == 10 ** 25
'validator_stake': staked_amount, 'validator_key': get_validator_key(i), 'peer_info': f'{get_pubkey(i)}@{machines[i].ip}:24567' }) # Generate config and genesis locally, apply changes to config/genesis locally for i in range(num_machines): node_dir = get_node_dir(i) shutil.copy(tempdir / 'accounts.csv', node_dir / 'accounts.csv') p = run('bash', input=f''' cd .. target/release/genesis-csv-to-json --home {node_dir} --chain-id pytest ''') apply_config_changes(node_dir, client_config_changes) apply_genesis_changes(node_dir, genesis_config_changes) pbar = tqdm(total=num_machines, desc=' upload nodedir') # Upload json and accounts.csv def upload_genesis_files(i): # stop if already start machines[i].run('tmux send-keys -t python-rc C-c') time.sleep(2) machines[i].kill_detach_tmux() machines[i].run('rm -rf ~/.near') # upload keys, config, genesis machines[i].upload(str(get_node_dir(i)), f'/home/{machines[i].username}/.near') pbar.update(1)
'is_treasury': 'true' if i == 0 else 'false', 'validator_stake': staked_amount, 'validator_key': get_validator_key(i), 'peer_info': f'{get_pubkey(i)}@{machines[i].ip}:24567' }) # Generate config and genesis locally, apply changes to config/genesis locally for i in range(num_machines): p = run('bash', input=f''' cp /tmp/near/accounts.csv /tmp/near/node{i} cd .. target/release/genesis-csv-to-json --home /tmp/near/node{i} --chain-id pytest ''') apply_config_changes(f'/tmp/near/node{i}', client_config_changes) apply_genesis_changes(f'/tmp/near/node{i}', genesis_config_changes) pbar = tqdm(total=num_machines, desc=' upload nodedir') # Upload json and accounts.csv def upload_genesis_files(i): # stop if already start machines[i].run('tmux send-keys -t python-rc C-c') time.sleep(2) machines[i].kill_detach_tmux() machines[i].run('rm -rf ~/.near') # upload keys, config, genesis machines[i].upload(f'/tmp/near/node{i}', f'/home/{machines[i].username}/.near') pbar.update(1)
def test_upgrade() -> None: """Test that upgrade from ‘stable’ to ‘current’ binary is possible. 1. Start a network with 3 `stable` nodes and 1 `new` node. 2. Start switching `stable` nodes one by one with `new` nodes. 3. Run for three epochs and observe that current protocol version of the network matches `new` nodes. """ executables = get_executables() node_root = utils.get_near_tempdir('upgradable', clean=True) # Setup local network. # TODO(#4372): testnet subcommand deprecated since 1.24. Replace with # localnet after a couple of releases in 2022. cmd = (executables.stable.neard, "--home=%s" % node_root, "testnet", "--v", "4", "--prefix", "test") logger.info(' '.join(str(arg) for arg in cmd)) subprocess.check_call(cmd) genesis_config_changes = [("epoch_length", 20), ("num_block_producer_seats", 10), ("num_block_producer_seats_per_shard", [10]), ("block_producer_kickout_threshold", 80), ("chunk_producer_kickout_threshold", 80), ("chain_id", "testnet")] node_dirs = [os.path.join(node_root, 'test%d' % i) for i in range(4)] for i, node_dir in enumerate(node_dirs): cluster.apply_genesis_changes(node_dir, genesis_config_changes) cluster.apply_config_changes(node_dir, {'tracked_shards': [0]}) # Start 3 stable nodes and one current node. config = executables.stable.node_config() nodes = [ cluster.spin_up_node(config, executables.stable.root, node_dirs[0], 0) ] for i in range(1, 3): nodes.append( cluster.spin_up_node(config, executables.stable.root, node_dirs[i], i, boot_node=nodes[0])) config = executables.current.node_config() nodes.append( cluster.spin_up_node(config, executables.current.root, node_dirs[3], 3, boot_node=nodes[0])) time.sleep(2) # deploy a contract hash = nodes[0].get_latest_block().hash_bytes tx = sign_deploy_contract_tx(nodes[0].signer_key, utils.load_test_contract(), 1, hash) res = nodes[0].send_tx_and_wait(tx, timeout=20) assert 'error' not in res, res # write some random value tx = sign_function_call_tx(nodes[0].signer_key, nodes[0].signer_key.account_id, 'write_random_value', [], 10**13, 0, 2, hash) res = nodes[0].send_tx_and_wait(tx, timeout=20) assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res utils.wait_for_blocks(nodes[0], count=20) # Restart stable nodes into new version. for i in range(3): nodes[i].kill() nodes[i].binary_name = config['binary_name'] nodes[i].start(boot_node=nodes[0]) utils.wait_for_blocks(nodes[3], count=60) status0 = nodes[0].get_status() status3 = nodes[3].get_status() protocol_version = status0['protocol_version'] latest_protocol_version = status3["latest_protocol_version"] assert protocol_version == latest_protocol_version, \ "Latest protocol version %d should match active protocol version %d" % ( latest_protocol_version, protocol_version) hash = base58.b58decode( status0['sync_info']['latest_block_hash'].encode('ascii')) # write some random value again tx = sign_function_call_tx(nodes[0].signer_key, nodes[0].signer_key.account_id, 'write_random_value', [], 10**13, 0, 4, hash) res = nodes[0].send_tx_and_wait(tx, timeout=20) assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res # hex_account_id = (b"I'm hex!" * 4).hex() hex_account_id = '49276d206865782149276d206865782149276d206865782149276d2068657821' tx = sign_payment_tx(key=nodes[0].signer_key, to=hex_account_id, amount=10**25, nonce=5, blockHash=hash) res = nodes[0].send_tx_and_wait(tx, timeout=20) # Successfully created a new account on transfer to hex assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res hex_account_balance = int( nodes[0].get_account(hex_account_id)['result']['amount']) assert hex_account_balance == 10**25
def main(): node_root = "/tmp/near/upgradable" if os.path.exists(node_root): shutil.rmtree(node_root) subprocess.check_output('mkdir -p /tmp/near', shell=True) branch = branches.latest_rc_branch() logger.info(f"Latest rc release branch is {branch}") near_root, (stable_branch, current_branch) = branches.prepare_ab_test(branch) # Setup local network. logger.info([ "%snear-%s" % (near_root, stable_branch), "--home=%s" % node_root, "testnet", "--v", "4", "--prefix", "test" ]) subprocess.call([ "%snear-%s" % (near_root, stable_branch), "--home=%s" % node_root, "testnet", "--v", "4", "--prefix", "test" ]) genesis_config_changes = [("epoch_length", 20), ("num_block_producer_seats", 10), ("num_block_producer_seats_per_shard", [10]), ("block_producer_kickout_threshold", 80), ("chunk_producer_kickout_threshold", 80), ("chain_id", "testnet")] node_dirs = [os.path.join(node_root, 'test%d' % i) for i in range(4)] for i, node_dir in enumerate(node_dirs): cluster.apply_genesis_changes(node_dir, genesis_config_changes) # Start 3 stable nodes and one current node. config = { "local": True, 'near_root': near_root, 'binary_name': "near-%s" % stable_branch } nodes = [ cluster.spin_up_node(config, near_root, node_dirs[0], 0, None, None) ] for i in range(1, 3): nodes.append( cluster.spin_up_node(config, near_root, node_dirs[i], i, nodes[0].node_key.pk, nodes[0].addr())) if os.getenv('NAYDUCK'): config["binary_name"] = "near" else: config["binary_name"] = "near-%s" % current_branch nodes.append( cluster.spin_up_node(config, near_root, node_dirs[3], 3, nodes[0].node_key.pk, nodes[0].addr())) time.sleep(2) # deploy a contract status = nodes[0].get_status() hash = status['sync_info']['latest_block_hash'] tx = sign_deploy_contract_tx(nodes[0].signer_key, load_test_contract(), 1, base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) assert 'error' not in res, res # write some random value tx = sign_function_call_tx(nodes[0].signer_key, nodes[0].signer_key.account_id, 'write_random_value', [], 10**13, 0, 2, base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res wait_for_blocks_or_timeout(nodes[0], 20, 120) # Restart stable nodes into new version. for i in range(3): nodes[i].kill() nodes[i].binary_name = config['binary_name'] nodes[i].start(nodes[0].node_key.pk, nodes[0].addr()) wait_for_blocks_or_timeout(nodes[3], 60, 120) status0 = nodes[0].get_status() status3 = nodes[3].get_status() protocol_version = status0['protocol_version'] latest_protocol_version = status3["latest_protocol_version"] assert protocol_version == latest_protocol_version, \ "Latest protocol version %d should match active protocol version %d" % ( latest_protocol_version, protocol_version) hash = status0['sync_info']['latest_block_hash'] # write some random value again tx = sign_function_call_tx(nodes[0].signer_key, nodes[0].signer_key.account_id, 'write_random_value', [], 10**13, 0, 4, base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res # hex_account_id = (b"I'm hex!" * 4).hex() hex_account_id = '49276d206865782149276d206865782149276d206865782149276d2068657821' tx = sign_payment_tx(key=nodes[0].signer_key, to=hex_account_id, amount=10**25, nonce=5, blockHash=base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) # Successfully created a new account on transfer to hex assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res hex_account_balance = int( nodes[0].get_account(hex_account_id)['result']['amount']) assert hex_account_balance == 10**25 hash = status0['sync_info']['latest_block_hash'] new_account_id = f'new.{nodes[0].signer_key.account_id}' new_signer_key = cluster.Key(new_account_id, nodes[0].signer_key.pk, nodes[0].signer_key.sk) create_account_tx = sign_create_account_with_full_access_key_and_balance_tx( nodes[0].signer_key, new_account_id, new_signer_key, 10**24, 6, base58.b58decode(hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(create_account_tx, timeout=20) # Successfully created a new account assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res hash = status0['sync_info']['latest_block_hash'] status = nodes[0].get_status() block_height = status['sync_info']['latest_block_height'] beneficiary_account_id = '1982374698376abd09265034ef35034756298375462323456294875193563756' tx = sign_delete_account_tx(key=new_signer_key, to=new_account_id, beneficiary=beneficiary_account_id, nonce=block_height * 1_000_000 - 1, block_hash=base58.b58decode( hash.encode('utf8'))) res = nodes[0].send_tx_and_wait(tx, timeout=20) # Successfully deleted an account assert 'error' not in res, res assert 'Failure' not in res['result']['status'], res