Skip to content

Commit

Permalink
Test upgrade to Conway
Browse files Browse the repository at this point in the history
  • Loading branch information
mkoura committed Jul 22, 2024
1 parent 4468342 commit a8a3a76
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 40 deletions.
1 change: 1 addition & 0 deletions .github/env_nightly_upgrade
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
BASE_TAR_URL=https://github.com/IntersectMBO/cardano-node/releases/download/8.12.2/cardano-node-8.12.2-linux.tar.gz
CI_BYRON_CLUSTER=true
UPGRADE_CLI_REVISION=release/cardano-cli-9.0.0.1
84 changes: 74 additions & 10 deletions .github/node_upgrade_pytest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export TX_ERA="$CLUSTER_ERA"

CLUSTER_SCRIPTS_DIR="$WORKDIR/cluster0_${CLUSTER_ERA}"
STATE_CLUSTER="${CARDANO_NODE_SOCKET_PATH_CI%/*}"
NUM_CC=5

# init dir for step1 binaries
STEP1_BIN="$WORKDIR/step1-bin"
Expand Down Expand Up @@ -67,9 +68,9 @@ if [ "$1" = "step1" ]; then
ln -s "$(command -v cardano-cli)" "$STEP1_BIN/cardano-cli-step1"

# backup the original genesis files
cp -f "$STATE_CLUSTER/shelley/genesis.alonzo.json" "$STATE_CLUSTER/shelley/genesis.alonzo-step1.json"
cp -f "$STATE_CLUSTER/shelley/genesis.alonzo.json" "$STATE_CLUSTER/shelley/genesis.alonzo.step1.json"
if [ -e "$STATE_CLUSTER/shelley/genesis.conway.json" ]; then
cp -f "$STATE_CLUSTER/shelley/genesis.conway.json" "$STATE_CLUSTER/shelley/genesis.conway-step1.json"
cp -f "$STATE_CLUSTER/shelley/genesis.conway.json" "$STATE_CLUSTER/shelley/genesis.conway.step1.json"
fi

# run smoke tests
Expand Down Expand Up @@ -103,6 +104,14 @@ elif [ "$1" = "step2" ]; then

export UPGRADE_TESTS_STEP=2

# Setup `cardano-cli` binary
if [ -n "${UPGRADE_CLI_REVISION:-""}" ]; then
export CARDANO_CLI_REV="$UPGRADE_CLI_REVISION"
# shellcheck disable=SC1090,SC1091
. .github/source_cardano_cli.sh
export PATH="$WORKDIR/cardano-cli/cardano-cli-build/bin":"$PATH"
fi

# add binaries saved in step1 to the PATH
export PATH="${STEP1_BIN}:${PATH}"

Expand Down Expand Up @@ -143,9 +152,9 @@ elif [ "$1" = "step2" ]; then
if [ "$fname" = "config-pool3.json" ]; then
# use old Alonzo and Conway genesis on pool3
selected_alonzo_hash="$ALONZO_GENESIS_STEP1_HASH"
selected_alonzo_file="shelley/genesis.alonzo-step1.json"
selected_alonzo_file="shelley/genesis.alonzo.step1.json"
selected_conway_hash="$CONWAY_GENESIS_STEP1_HASH"
selected_conway_file="shelley/genesis.conway-step1.json"
selected_conway_file="shelley/genesis.conway.step1.json"
else
# use new Alonzo and Conway genesis on upgraded nodes
selected_alonzo_hash="$ALONZO_GENESIS_HASH"
Expand Down Expand Up @@ -186,7 +195,7 @@ elif [ "$1" = "step2" ]; then
done

# run the pool3 with the original cardano-node binary
cp -a "$STATE_CLUSTER/cardano-node-pool3" "$STATE_CLUSTER/cardano-node-pool3.orig"
cp -f "$STATE_CLUSTER/cardano-node-pool3" "$STATE_CLUSTER/cardano-node-pool3.orig"
sed -i 's/cardano-node run/cardano-node-step1 run/' "$STATE_CLUSTER/cardano-node-pool3"

# Restart local cluster nodes with binaries from new cluster-node version.
Expand Down Expand Up @@ -233,6 +242,7 @@ elif [ "$1" = "step2" ]; then

# Test for ignoring expected errors in log files. Run separately to make sure it runs first.
pytest cardano_node_tests/tests/test_node_upgrade.py -k test_ignore_log_errors
err_retval="$?"

# run smoke tests
pytest \
Expand All @@ -253,6 +263,8 @@ elif [ "$1" = "step2" ]; then
./.github/results.sh .
mv allure-results.tar.xz allure-results-step2.tar.xz

[ "$err_retval" -gt "$retval" ] && retval=1

printf "STEP2 finish: %(%H:%M:%S)T\n" -1


Expand All @@ -265,6 +277,17 @@ elif [ "$1" = "step3" ]; then

export UPGRADE_TESTS_STEP=3

# Setup `cardano-cli` binary
if [ -n "${UPGRADE_CLI_REVISION:-""}" ]; then
export CARDANO_CLI_REV="$UPGRADE_CLI_REVISION"
# the cardano-cli binary is already built in step2
if [ ! -e "$WORKDIR/cardano-cli/cardano-cli-build/bin/cardano-cli" ]; then
echo "Failed to find the requested 'cardano-cli' binary" >&2
exit 6
fi
export PATH="$WORKDIR/cardano-cli/cardano-cli-build/bin":"$PATH"
fi

# generate config and topology files for p2p mode
CARDANO_NODE_SOCKET_PATH="$WORKDIR/dry_p2p/state-cluster0/bft1.socket" \
ENABLE_P2P=1 \
Expand All @@ -274,11 +297,42 @@ elif [ "$1" = "step3" ]; then
# copy newly generated topology files to the cluster state dir
cp -f "$WORKDIR"/dry_p2p/state-cluster0/topology-*.json "$STATE_CLUSTER"

# copy newly generated config files to the cluster state dir, but use the original genesis files
# Create committee keys
mkdir -p "$STATE_CLUSTER/governance_data"
for i in $(seq 1 "$NUM_CC"); do
cardano-cli conway governance committee key-gen-cold \
--cold-verification-key-file "$STATE_CLUSTER/governance_data/cc_member${i}_committee_cold.vkey" \
--cold-signing-key-file "$STATE_CLUSTER/governance_data/cc_member${i}_committee_cold.skey"
cardano-cli conway governance committee key-gen-hot \
--verification-key-file "$STATE_CLUSTER/governance_data/cc_member${i}_committee_hot.vkey" \
--signing-key-file "$STATE_CLUSTER/governance_data/cc_member${i}_committee_hot.skey"
cardano-cli conway governance committee create-hot-key-authorization-certificate \
--cold-verification-key-file "$STATE_CLUSTER/governance_data/cc_member${i}_committee_cold.vkey" \
--hot-verification-key-file "$STATE_CLUSTER/governance_data/cc_member${i}_committee_hot.vkey" \
--out-file "$STATE_CLUSTER/governance_data/cc_member${i}_committee_hot_auth.cert"
cardano-cli conway governance committee key-hash \
--verification-key-file "$STATE_CLUSTER/governance_data/cc_member${i}_committee_cold.vkey" \
> "$STATE_CLUSTER/governance_data/cc_member${i}_committee_cold.hash"
done

# Pre-register committee in genesis
cp -f "$STATE_CLUSTER/shelley/genesis.conway.json" "$STATE_CLUSTER/shelley/genesis.conway.step2.json"
KEY_HASH_JSON=$(jq -nR '[inputs | {("keyHash-" + .): 10000}] | add' \
"$STATE_CLUSTER"/governance_data/cc_member*_committee_cold.hash)
jq \
--argjson keyHashJson "$KEY_HASH_JSON" \
'.committee.members = $keyHashJson
| .committee.threshold = 0.6
| .committeeMinSize = 2' \
"$STATE_CLUSTER/shelley/genesis.conway.step2.json" > "$STATE_CLUSTER/shelley/genesis.conway.json"

# Copy newly generated config files to the cluster state dir, but use the original genesis files
BYRON_GENESIS_HASH="$(jq -r ".ByronGenesisHash" "$STATE_CLUSTER/config-bft1.json")"
SHELLEY_GENESIS_HASH="$(jq -r ".ShelleyGenesisHash" "$STATE_CLUSTER/config-bft1.json")"
ALONZO_GENESIS_HASH="$(jq -r ".AlonzoGenesisHash" "$STATE_CLUSTER/config-bft1.json")"
CONWAY_GENESIS_HASH="$(jq -r ".ConwayGenesisHash" "$STATE_CLUSTER/config-bft1.json")"
# Use the new Conway genesis
CONWAY_GENESIS_HASH="$(cardano-cli genesis hash --genesis \
"$STATE_CLUSTER/shelley/genesis.conway.json")"
for conf in "$WORKDIR"/dry_p2p/state-cluster0/config-*.json; do
fname="${conf##*/}"
jq \
Expand All @@ -289,12 +343,12 @@ elif [ "$1" = "step3" ]; then
'.ByronGenesisHash = $byron_hash
| .ShelleyGenesisHash = $shelley_hash
| .AlonzoGenesisHash = $alonzo_hash
| .ConwayHash = $conway_hash' \
| .ConwayGenesisHash = $conway_hash' \
"$conf" > "$STATE_CLUSTER/$fname"
done

# use the upgraded cardano-node binary for pool3
cp -a "$STATE_CLUSTER/cardano-node-pool3.orig" "$STATE_CLUSTER/cardano-node-pool3"
cp -f "$STATE_CLUSTER/cardano-node-pool3.orig" "$STATE_CLUSTER/cardano-node-pool3"

# restart all nodes
"$STATE_CLUSTER/supervisorctl" restart nodes:
Expand All @@ -315,8 +369,16 @@ elif [ "$1" = "step3" ]; then

# Test for ignoring expected errors in log files. Run separately to make sure it runs first.
pytest cardano_node_tests/tests/test_node_upgrade.py -k test_ignore_log_errors
err_retval="$?"

# run smoke tests
# Update to Conway
pytest cardano_node_tests/tests/test_node_upgrade.py -k test_update_to_conway_pv9 || exit 6

# From now on, we are in the Conway era
unset TX_ERA
export CLUSTER_ERA=conway COMMAND_ERA=conway

# Run smoke tests
pytest \
cardano_node_tests \
-n "$TEST_THREADS" \
Expand All @@ -332,6 +394,8 @@ elif [ "$1" = "step3" ]; then
./.github/results.sh .
mv allure-results.tar.xz allure-results-step3.tar.xz

[ "$err_retval" -gt "$retval" ] && retval=1

printf "STEP3 finish: %(%H:%M:%S)T\n" -1

#
Expand Down
151 changes: 121 additions & 30 deletions cardano_node_tests/tests/test_node_upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

from cardano_node_tests.cluster_management import cluster_management
from cardano_node_tests.tests import common
from cardano_node_tests.utils import cluster_nodes
from cardano_node_tests.utils import clusterlib_utils
from cardano_node_tests.utils import governance_utils
from cardano_node_tests.utils import helpers
from cardano_node_tests.utils import logfiles
from cardano_node_tests.utils import temptools
Expand All @@ -22,40 +24,35 @@
UPGRADE_TESTS_STEP = int(os.environ.get("UPGRADE_TESTS_STEP") or 0)
BASE_REVISION = version.parse(os.environ.get("BASE_REVISION") or "0.0.0")
UPGRADE_REVISION = version.parse(os.environ.get("UPGRADE_REVISION") or "0.0.0")
GOV_DATA_DIR = "governance_data"

pytestmark = [
pytest.mark.skipif(not UPGRADE_TESTS_STEP, reason="not upgrade testing"),
]


@pytest.fixture
def payment_addrs_locked(
def payment_addr_locked(
cluster_manager: cluster_management.ClusterManager,
cluster_singleton: clusterlib.ClusterLib,
) -> tp.List[clusterlib.AddressRecord]:
) -> clusterlib.AddressRecord:
"""Create new payment addresses."""
cluster = cluster_singleton
temp_template = common.get_test_id(cluster)

with cluster_manager.cache_fixture() as fixture_cache:
if fixture_cache.value:
return fixture_cache.value # type: ignore

addrs = clusterlib_utils.create_payment_addr_records(
f"{temp_template}_payment_addr_0",
f"{temp_template}_payment_addr_1",
cluster_obj=cluster,
)
fixture_cache.value = addrs
addr = clusterlib_utils.create_payment_addr_records(
f"{temp_template}_payment_addr_0",
cluster_obj=cluster,
)[0]

# fund source addresses
clusterlib_utils.fund_from_faucet(
addrs[0],
addr,
cluster_obj=cluster,
faucet_data=cluster_manager.cache.addrs_data["user1"],
)

return addrs
return addr


@pytest.fixture
Expand Down Expand Up @@ -99,29 +96,123 @@ def test_ignore_log_errors(
cluster = cluster_singleton
common.get_test_id(cluster)

# Ignore ledger replay when upgrading from node version 1.34.1.
# The error message appears only right after the node is upgraded. This ignore rule has
# effect only in this test.
if version.parse("1.34.1") == BASE_REVISION:
if UPGRADE_REVISION >= version.parse("9.0.0") > BASE_REVISION:
logfiles.add_ignore_rule(
files_glob="*.stdout",
regex="ChainDB:Error:.* Invalid snapshot DiskSnapshot .*DeserialiseFailure 168 ",
regex="ChainDB:Error:.* Invalid snapshot DiskSnapshot .*DeserialiseFailure "
".*expected list len or indef",
ignore_file_id=worker_id,
)
elif UPGRADE_REVISION >= version.parse("1.36.0") > BASE_REVISION:
logfiles.add_ignore_rule(
files_glob="*.stdout",
regex="ChainDB:Error:.* Invalid snapshot DiskSnapshot .*DeserialiseFailure 5 ",
ignore_file_id=worker_id,

@allure.link(helpers.get_vcs_link())
@pytest.mark.skipif(UPGRADE_TESTS_STEP != 3, reason="runs only on step 3 of upgrade testing")
def test_update_to_conway_pv9(
self,
cluster_singleton: clusterlib.ClusterLib,
payment_addr_locked: clusterlib.AddressRecord,
):
"""Update cluster to Conway PV9."""
cluster = cluster_singleton
temp_template = common.get_test_id(cluster)

def _update_to_pv9() -> None:
cluster.wait_for_new_epoch()

update_proposal_pv9 = [
clusterlib_utils.UpdateProposal(
arg="--protocol-major-version",
value=9,
name="", # needs custom check
),
clusterlib_utils.UpdateProposal(
arg="--protocol-minor-version",
value=0,
name="", # needs custom check
),
]

clusterlib_utils.update_params(
cluster_obj=cluster,
src_addr_record=payment_addr_locked,
update_proposals=update_proposal_pv9,
)
elif UPGRADE_REVISION >= version.parse("8.1.0") > BASE_REVISION:
logfiles.add_ignore_rule(
files_glob="*.stdout",
regex="ChainDB:Error:.* Invalid snapshot DiskSnapshot .*DeserialiseFailure "
".*Size mismatch when decoding Record RecD",
ignore_file_id=worker_id,

cluster.wait_for_new_epoch(padding_seconds=3)

prot_ver = cluster.g_query.get_protocol_params()["protocolVersion"]
assert prot_ver["major"] == 9
assert prot_ver["minor"] == 0

def _load_cc_members(
cluster_obj: clusterlib.ClusterLib,
) -> tp.List[governance_utils.CCMemberAuth]:
data_dir = cluster_obj.state_dir / GOV_DATA_DIR

cc_members = []
for vkey_file in sorted(data_dir.glob("cc_member*_committee_cold.vkey")):
fpath = vkey_file.parent
fbase = vkey_file.name.replace("cold.vkey", "")
hot_vkey_file = fpath / f"{fbase}hot.vkey"
cold_vkey_hash = cluster_obj.g_conway_governance.committee.get_key_hash(
vkey_file=vkey_file
)
auth_cert = fpath / f"{fbase}hot_auth.cert"
cold_key_pair = clusterlib.KeyPair(
vkey_file=vkey_file, skey_file=fpath / f"{fbase}cold.skey"
)
hot_key_pair = clusterlib.KeyPair(
vkey_file=hot_vkey_file, skey_file=fpath / f"{fbase}hot.skey"
)
cc_members.append(
governance_utils.CCMemberAuth(
auth_cert=auth_cert,
cold_key_pair=cold_key_pair,
hot_key_pair=hot_key_pair,
key_hash=cold_vkey_hash,
)
)

return cc_members

def _reg_cc_members(
cluster_obj: clusterlib.ClusterLib, cc_members: tp.List[governance_utils.CCMemberAuth]
) -> None:
tx_files = clusterlib.TxFiles(
certificate_files=[c.auth_cert for c in cc_members],
signing_key_files=[
payment_addr_locked.skey_file,
*[c.cold_key_pair.skey_file for c in cc_members],
],
)

tx_output_auth = clusterlib_utils.build_and_submit_tx(
cluster_obj=cluster_obj,
name_template=f"{temp_template}_auth",
src_address=payment_addr_locked.address,
tx_files=tx_files,
)

auth_out_utxos = cluster_obj.g_query.get_utxo(tx_raw_output=tx_output_auth)
assert (
clusterlib.filter_utxos(utxos=auth_out_utxos, address=payment_addr_locked.address)[
0
].amount
== clusterlib.calculate_utxos_balance(tx_output_auth.txins) - tx_output_auth.fee
), f"Incorrect balance for source address `{payment_addr_locked.address}`"

auth_committee_state = cluster_obj.g_conway_governance.query.committee_state()
for cm in cc_members:
member_key = f"keyHash-{cm.key_hash}"
member_rec = auth_committee_state["committee"][member_key]
assert (
member_rec["hotCredsAuthStatus"]["tag"] == "MemberAuthorized"
), "CC Member was NOT authorized"

_update_to_pv9()
cluster_conway = cluster_nodes.get_cluster_type().get_cluster_obj(command_era="conway")
cc_members = _load_cc_members(cluster_obj=cluster_conway)
_reg_cc_members(cluster_obj=cluster_conway, cc_members=cc_members)


@pytest.mark.upgrade
class TestUpgrade:
Expand Down

0 comments on commit a8a3a76

Please sign in to comment.