Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: implement era switch in e2e tests #1974

Merged
merged 16 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ jobs:
matrix:
mode: ["std"]
era: ${{ fromJSON(needs.build-ubuntu-X64.outputs.eras) }}
next_era: [""]
cardano_node_version: ["9.0.0", "9.1.0", "9.1.1", "9.2.0", "9.2.1"]
hard_fork_latest_era_at_epoch: [0]
run_id: ["#1"]
Expand All @@ -298,10 +299,27 @@ jobs:
# Include a test for the P2P mode
- mode: "p2p"
era: ${{ fromJSON(needs.build-ubuntu-X64.outputs.eras)[0] }}
next_era: [""]
cardano_node_version: "9.1.1"
hard_fork_latest_era_at_epoch: 0
run_id: "#1"
extra_args: "--use-p2p-network"
# Include a test for the era switch without regenesis
- mode: "std"
era: ${{ fromJSON(needs.build-ubuntu-X64.outputs.eras)[0] }}
next_era: ${{ fromJSON(needs.build-ubuntu-X64.outputs.eras)[1] }}
jpraynaud marked this conversation as resolved.
Show resolved Hide resolved
cardano_node_version: "9.1.1"
hard_fork_latest_era_at_epoch: 0
run_id: "#1"
extra_args: ""
# Include a test for the era switch with regenesis
- mode: "std"
era: ${{ fromJSON(needs.build-ubuntu-X64.outputs.eras)[0] }}
next_era: ${{ fromJSON(needs.build-ubuntu-X64.outputs.eras)[1] }}
cardano_node_version: "9.1.1"
hard_fork_latest_era_at_epoch: 0
run_id: "#1"
extra_args: "--mithril-era-regenesis-on-switch"
steps:
- name: Checkout sources
uses: actions/checkout@v4
Expand All @@ -328,13 +346,24 @@ jobs:

- name: Test
run: |
./mithril-end-to-end -vvv \
--bin-directory ./bin \
--work-directory=./artifacts \
--devnet-scripts-directory=./mithril-test-lab/mithril-devnet \
--mithril-era=${{ matrix.era }} \
--cardano-node-version ${{ matrix.cardano_node_version }} \
--cardano-hard-fork-latest-era-at-epoch ${{ matrix.hard_fork_latest_era_at_epoch }} ${{ matrix.extra_args }}
cat > ./mithril-end-to-end.sh << EOF
#!/bin/bash
set -x
./mithril-end-to-end -vvv \\
--bin-directory ./bin \\
--work-directory=./artifacts \\
--devnet-scripts-directory=./mithril-test-lab/mithril-devnet \\
--mithril-era=${{ matrix.era }} \\
--cardano-node-version ${{ matrix.cardano_node_version }} \\
--cardano-hard-fork-latest-era-at-epoch ${{ matrix.hard_fork_latest_era_at_epoch }} ${{ matrix.extra_args }} \\
EOF
# If there is a next era, we need to specify it with '--mithril-next-era'
if [[ "${{ matrix.next_era }}" != "" ]]; then
echo " --mithril-next-era=${{ matrix.next_era }}" >> ./mithril-end-to-end.sh
fi
chmod u+x ./mithril-end-to-end.sh
./mithril-end-to-end.sh
rm ./mithril-end-to-end.sh

- name: Upload E2E Tests Artifacts
if: ${{ failure() }}
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ As a minor extension, we have adopted a slightly different versioning convention

- Support for stable Cardano transaction client library, CLI and WASM.

- Support for Mithril era switch in end to end test.

- Crates versions:

| Crate | Version |
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mithril-test-lab/mithril-devnet/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.1
0.4.2
2 changes: 0 additions & 2 deletions mithril-test-lab/mithril-devnet/mkfiles/mkfiles-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ GENESIS_SECRET_KEY=5b3131382c3138342c3232342c3137332c3136302c3234312c36312c31343
CHAIN_OBSERVER_TYPE=pallas

cat >> docker-compose.yaml <<EOF
version: "3.9"

services:
EOF

Expand Down
48 changes: 33 additions & 15 deletions mithril-test-lab/mithril-devnet/mkfiles/mkfiles-mithril-era.sh
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,19 @@ function send_funds_to_era_address {
--tx-file node-pool${N}/tx/tx${N}-era-funds.tx \\
--testnet-magic ${NETWORK_MAGIC}

## Compute the submitted transaction id
TX_ID_SUBMITTED=\$(CARDANO_NODE_SOCKET_PATH=node-pool${N}/ipc/node.sock $CARDANO_CLI \${CURRENT_CARDANO_ERA} transaction txid --tx-file node-pool${N}/tx/tx${N}-era-funds.tx)

## Wait at least for 10 blocks so that the transaction is confirmed
wait_for_elapsed_blocks 10

## Wait for all pool nodes to see the new funds
## Wait for all pool nodes to see the new transaction
for (( i=1; i<=${NUM_POOL_NODES}; i++ )); do
AMOUNT_RETRIEVED=\$(CARDANO_NODE_SOCKET_PATH=node-pool\${i}/ipc/node.sock $CARDANO_CLI query utxo \\
TOTAL_UTXOS_FOR_TX_ID=\$(CARDANO_NODE_SOCKET_PATH=node-pool\${i}/ipc/node.sock $CARDANO_CLI query utxo \\
--testnet-magic ${NETWORK_MAGIC} --address \$(cat addresses/${ADDR}.addr) --out-file /dev/stdout \\
| jq '. [] | select(.value.lovelace | . != null and . != "") | .value.lovelace')
| jq '. | with_entries(select(.key | startswith("${TX_ID_SUBMITTED}"))) | length')
echo ">>>>>> Era address funds retrieved on node-pool\${i}: \${AMOUNT_RETRIEVED}"
if [ "\${AMOUNT_RETRIEVED}" != "${AMOUNT_TRANSFERRED}" ]; then
if [ "\${TOTAL_UTXOS_FOR_TX_ID}" == "0" ]; then
touch ${MITHRIL_ERA_ERROR_FILE}
break
fi
Expand Down Expand Up @@ -139,20 +142,35 @@ function write_datums_for_era_address {
# Remove if exists previous error file
rm -f ${MITHRIL_ERA_ERROR_FILE}

# Write the era datum on chain
TX_IN=\$(CARDANO_NODE_SOCKET_PATH=node-pool${N}/ipc/node.sock $CARDANO_CLI query utxo \\
# Fetch transactions from UTxOs of the era address
TX_IN_DATUM=\$(CARDANO_NODE_SOCKET_PATH=node-pool${N}/ipc/node.sock $CARDANO_CLI query utxo \\
--testnet-magic ${NETWORK_MAGIC} --address \$(cat addresses/${ADDR}.addr) --out-file /dev/stdout \\
| jq -r 'to_entries | map({utxo: .key} + .value) | . [] | select(.inlineDatum | . != null and . != "") | .utxo')
TX_IN_NO_DATUM=\$(CARDANO_NODE_SOCKET_PATH=node-pool${N}/ipc/node.sock $CARDANO_CLI query utxo \\
--testnet-magic ${NETWORK_MAGIC} --address \$(cat addresses/${ADDR}.addr) --out-file /dev/stdout \\
| jq -r 'to_entries | [last] | .[0].key')

## Build the transaction
CARDANO_NODE_SOCKET_PATH=node-pool${N}/ipc/node.sock $CARDANO_CLI \${CURRENT_CARDANO_ERA} transaction build \\
--tx-in \${TX_IN} \\
--tx-out \$(cat addresses/${ADDR}.addr)+${SCRIPT_TX_VALUE} \\
--tx-out-inline-datum-file \${DATUM_FILE} \\
--change-address \$(cat addresses/${ADDR}.addr) \\
--testnet-magic ${NETWORK_MAGIC} \\
--invalid-hereafter 100000 \\
--out-file node-pool${N}/tx/tx${N}-era-datum.txbody
if [ "\${TX_IN_DATUM}" == "" ]; then
CARDANO_NODE_SOCKET_PATH=node-pool${N}/ipc/node.sock $CARDANO_CLI \${CURRENT_CARDANO_ERA} transaction build \\
--tx-in \${TX_IN_NO_DATUM} \\
--tx-out \$(cat addresses/${ADDR}.addr)+${SCRIPT_TX_VALUE} \\
--tx-out-inline-datum-file \${DATUM_FILE} \\
--change-address \$(cat addresses/${ADDR}.addr) \\
--testnet-magic ${NETWORK_MAGIC} \\
--invalid-hereafter 100000 \\
--out-file node-pool${N}/tx/tx${N}-era-datum.txbody
else
CARDANO_NODE_SOCKET_PATH=node-pool${N}/ipc/node.sock $CARDANO_CLI \${CURRENT_CARDANO_ERA} transaction build \\
--tx-in \${TX_IN_DATUM} \\
--tx-in \${TX_IN_NO_DATUM} \\
--tx-out \$(cat addresses/${ADDR}.addr)+${SCRIPT_TX_VALUE} \\
--tx-out-inline-datum-file \${DATUM_FILE} \\
--change-address \$(cat addresses/${ADDR}.addr) \\
--testnet-magic ${NETWORK_MAGIC} \\
--invalid-hereafter 100000 \\
--out-file node-pool${N}/tx/tx${N}-era-datum.txbody
fi

## Sign the transaction
CARDANO_NODE_SOCKET_PATH=node-pool${N}/ipc/node.sock $CARDANO_CLI \${CURRENT_CARDANO_ERA} transaction sign \\
Expand All @@ -173,7 +191,7 @@ function write_datums_for_era_address {
for (( i=1; i<=${NUM_POOL_NODES}; i++ )); do
INLINE_DATUM=\$(CARDANO_NODE_SOCKET_PATH=node-pool\${i}/ipc/node.sock $CARDANO_CLI query utxo \\
--testnet-magic ${NETWORK_MAGIC} --address \$(cat addresses/${ADDR}.addr) --out-file /dev/stdout \\
| jq -r '. [] | select(.inlineDatum | . != null and . != "") | .inlineDatum.fields[].bytes' | xxd -r -p)
| jq -r '. [] | select(.inlineDatum | . != null and . != "") | .inlineDatum.fields[].bytes' | xxd -r -p | jq)
echo ">>>>>> Era address inline datum retrieved on node-pool\${i}: \${INLINE_DATUM}"
if [ "\${INLINE_DATUM}" == "" ]; then
touch ${MITHRIL_ERA_ERROR_FILE}
Expand Down
2 changes: 1 addition & 1 deletion mithril-test-lab/mithril-end-to-end/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-end-to-end"
version = "0.4.36"
version = "0.4.37"
authors = { workspace = true }
edition = { workspace = true }
documentation = { workspace = true }
Expand Down
9 changes: 5 additions & 4 deletions mithril-test-lab/mithril-end-to-end/src/assertions/exec.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::PathBuf;

use crate::{Aggregator, Devnet};
use mithril_common::entities::ProtocolParameters;
use mithril_common::entities::{Epoch, ProtocolParameters};
use mithril_common::StdResult;
use slog_scope::info;

Expand All @@ -22,18 +22,19 @@ pub async fn register_era_marker(
aggregator: &mut Aggregator,
devnet: &Devnet,
mithril_era: &str,
era_epoch: Epoch,
) -> StdResult<()> {
info!("Register era marker");
info!("Register '{mithril_era}' era marker");

info!("> generating era marker tx datum...");
let tx_datum_file_path = devnet
.artifacts_dir()
.join(PathBuf::from("era-tx-datum.txt".to_string()));
aggregator
.era_generate_tx_datum(&tx_datum_file_path, mithril_era)
.era_generate_tx_datum(&tx_datum_file_path, mithril_era, era_epoch)
.await?;

info!("> writing era marker on the Cardano chain...");
info!("> writing '{mithril_era}' era marker on the Cardano chain...");
devnet.write_era_marker(&tx_datum_file_path).await?;

Ok(())
Expand Down
77 changes: 71 additions & 6 deletions mithril-test-lab/mithril-end-to-end/src/end_to_end_spec.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
use crate::assertions;
use crate::MithrilInfrastructure;
use mithril_common::StdResult;
use mithril_common::{
entities::{Epoch, SignedEntityTypeDiscriminants},
StdResult,
};

pub struct Spec<'a> {
pub infrastructure: &'a mut MithrilInfrastructure,
is_signing_cardano_transactions: bool,
is_signing_cardano_stake_distribution: bool,
next_era: Option<String>,
regenesis_on_era_switch: bool,
}

impl<'a> Spec<'a> {
pub fn new(infrastructure: &'a mut MithrilInfrastructure) -> Self {
Self { infrastructure }
pub fn new(
infrastructure: &'a mut MithrilInfrastructure,
signed_entity_types: Vec<String>,
next_era: Option<String>,
regenesis_on_era_switch: bool,
) -> Self {
Self {
infrastructure,
is_signing_cardano_transactions: signed_entity_types.contains(
&SignedEntityTypeDiscriminants::CardanoTransactions
.as_ref()
.to_string(),
),
is_signing_cardano_stake_distribution: signed_entity_types.contains(
&SignedEntityTypeDiscriminants::CardanoStakeDistribution
.as_ref()
.to_string(),
),
next_era,
regenesis_on_era_switch,
}
}

pub async fn run(&mut self) -> StdResult<()> {
Expand Down Expand Up @@ -71,6 +97,45 @@ impl<'a> Spec<'a> {
)
.await?;

// Verify that artifacts are produced and signed correctly
let mut target_epoch = self.verify_artifacts_production(target_epoch).await?;

// Verify that artifacts are produced and signed correctly after era switch
if let Some(next_era) = &self.next_era {
// Switch to next era
self.infrastructure
.register_switch_to_next_era(next_era)
.await?;
target_epoch += 5;
assertions::wait_for_target_epoch(
self.infrastructure.chain_observer(),
target_epoch,
"epoch after which the era switch will have triggered".to_string(),
)
.await?;

// Proceed to a re-genesis of the certificate chain
if self.regenesis_on_era_switch {
assertions::bootstrap_genesis_certificate(self.infrastructure.aggregator_mut())
.await?;
target_epoch += 5;
assertions::wait_for_target_epoch(
self.infrastructure.chain_observer(),
target_epoch,
"epoch after which the re-genesis on era switch will be completed".to_string(),
)
.await?;
}

// Verify that artifacts are produced and signed correctly
self.verify_artifacts_production(target_epoch).await?;
}

Ok(())
}

async fn verify_artifacts_production(&self, target_epoch: Epoch) -> StdResult<Epoch> {
let aggregator_endpoint = self.infrastructure.aggregator().endpoint();
let expected_epoch_min = target_epoch - 3;
// Verify that mithril stake distribution artifacts are produced and signed correctly
{
Expand Down Expand Up @@ -116,7 +181,7 @@ impl<'a> Spec<'a> {
}

// Verify that Cardano transactions artifacts are produced and signed correctly
if self.infrastructure.is_signing_cardano_transactions() {
if self.is_signing_cardano_transactions {
let hash = assertions::assert_node_producing_cardano_transactions(&aggregator_endpoint)
.await?;
let certificate_hash = assertions::assert_signer_is_signing_cardano_transactions(
Expand All @@ -143,7 +208,7 @@ impl<'a> Spec<'a> {
}

// Verify that Cardano stake distribution artifacts are produced and signed correctly
if self.infrastructure.is_signing_cardano_stake_distribution() {
if self.is_signing_cardano_stake_distribution {
{
let (hash, epoch) = assertions::assert_node_producing_cardano_stake_distribution(
&aggregator_endpoint,
Expand Down Expand Up @@ -173,6 +238,6 @@ impl<'a> Spec<'a> {
}
}

Ok(())
Ok(target_epoch)
}
}
18 changes: 16 additions & 2 deletions mithril-test-lab/mithril-end-to-end/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ pub struct Args {
#[clap(long, default_value = "thales")]
mithril_era: String,

/// Mithril next era to run
#[clap(long)]
mithril_next_era: Option<String>,

/// Mithril re-genesis on era switch (used only when 'mithril_next_era' is set)
#[clap(long, default_value_t = false)]
mithril_era_regenesis_on_switch: bool,

/// Mithril era reader adapter
#[clap(long, default_value = "cardano-chain")]
mithril_era_reader_adapter: String,
Expand Down Expand Up @@ -191,10 +199,11 @@ async fn main() -> StdResult<()> {
mithril_run_interval: args.mithril_run_interval,
mithril_era: args.mithril_era,
mithril_era_reader_adapter: args.mithril_era_reader_adapter,
signed_entity_types: args.signed_entity_types,
signed_entity_types: args.signed_entity_types.clone(),
run_only_mode,
use_p2p_network_mode,
use_p2p_passive_relays,
use_era_specific_work_dir: args.mithril_next_era.is_some(),
})
.await?;

Expand All @@ -204,7 +213,12 @@ async fn main() -> StdResult<()> {
run_only.start().await
}
false => {
let mut spec = Spec::new(&mut infrastructure);
let mut spec = Spec::new(
&mut infrastructure,
args.signed_entity_types,
args.mithril_next_era,
args.mithril_era_regenesis_on_switch,
);
spec.run().await
}
};
Expand Down
Loading
Loading