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

refactor: enhance migration testing tool #17246

Merged
merged 15 commits into from
Jan 14, 2025
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
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
/*
* Copyright (C) 2025 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

plugins { id("org.hiero.gradle.module.application") }

application.mainClass = "com.swirlds.demo.migration.MigrationTestingToolMain"

testModuleInfo {
requires("org.junit.jupiter.api")
requires("org.assertj.core")
requires("org.junit.jupiter.params")
requires("org.mockito")
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import static com.swirlds.platform.test.fixtures.state.FakeStateLifecycles.registerMerkleStateRootClassIds;

import com.hedera.hapi.node.state.roster.RosterEntry;
import com.hedera.hapi.platform.event.StateSignatureTransaction;
import com.hedera.pbj.runtime.io.buffer.Bytes;
import com.swirlds.common.constructable.ClassConstructorPair;
import com.swirlds.common.constructable.ConstructableRegistry;
import com.swirlds.common.constructable.ConstructableRegistryException;
Expand Down Expand Up @@ -207,4 +209,10 @@
public BasicSoftwareVersion getSoftwareVersion() {
return softwareVersion;
}

@Override
@NonNull
public Bytes encodeSystemTransaction(final @NonNull StateSignatureTransaction transaction) {
return StateSignatureTransaction.PROTOBUF.toBytes(transaction);

Check warning on line 216 in platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java

View check run for this annotation

Codecov / codecov/patch

platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java#L216

Added line #L216 was not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
package com.swirlds.demo.migration;

import static com.swirlds.demo.migration.MigrationTestingToolMain.PREVIOUS_SOFTWARE_VERSION;
import static com.swirlds.demo.migration.TransactionUtils.isSystemTransaction;
import static com.swirlds.logging.legacy.LogMarker.STARTUP;
import static com.swirlds.platform.test.fixtures.state.FakeStateLifecycles.FAKE_MERKLE_STATE_LIFECYCLES;

import com.hedera.hapi.node.base.SemanticVersion;
import com.hedera.hapi.platform.event.StateSignatureTransaction;
import com.hedera.pbj.runtime.ParseException;
import com.swirlds.common.constructable.ConstructableIgnored;
import com.swirlds.common.crypto.DigestType;
import com.swirlds.common.merkle.MerkleNode;
Expand All @@ -47,7 +49,9 @@
import com.swirlds.platform.system.SoftwareVersion;
import com.swirlds.platform.system.address.AddressBook;
import com.swirlds.platform.system.events.ConsensusEvent;
import com.swirlds.platform.system.events.Event;
import com.swirlds.platform.system.transaction.ConsensusTransaction;
import com.swirlds.platform.system.transaction.Transaction;
import com.swirlds.virtualmap.VirtualMap;
import com.swirlds.virtualmap.datasource.VirtualDataSourceBuilder;
import edu.umd.cs.findbugs.annotations.NonNull;
Expand Down Expand Up @@ -278,6 +282,27 @@
}
}

@Override
public void preHandle(
final @NonNull Event event,
final @NonNull Consumer<ScopedSystemTransaction<StateSignatureTransaction>> stateSignatureTransaction) {
event.forEachTransaction(transaction -> {

// We don't want to consume deprecated EventTransaction.STATE_SIGNATURE_TRANSACTION system transactions in
// the callback, since it's intended to be used only
// for the new form of encoded system transactions in Bytes.
// We skip the current iteration, if it processes a deprecated system transaction with the
// EventTransaction.STATE_SIGNATURE_TRANSACTION type.
if (transaction.isSystem()) {
return;

Check warning on line 297 in platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java

View check run for this annotation

Codecov / codecov/patch

platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java#L297

Added line #L297 was not covered by tests
}

if (isSystemTransaction(transaction.getApplicationTransaction())) {
consumeSystemTransaction(transaction, event, stateSignatureTransaction);
}
});
}

/**
* {@inheritDoc}
*/
Expand All @@ -295,6 +320,11 @@
if (trans.isSystem()) {
continue;
}
if (isSystemTransaction(trans.getApplicationTransaction())) {
consumeSystemTransaction(trans, event, stateSignatureTransaction);
continue;
}

final MigrationTestingToolTransaction mTrans =
TransactionUtils.parseTransaction(trans.getApplicationTransaction());
mTrans.applyTo(this);
Expand Down Expand Up @@ -335,4 +365,19 @@
public int getMinimumSupportedVersion() {
return ClassVersion.VIRTUAL_MAP;
}

private void consumeSystemTransaction(
final @NonNull Transaction transaction,
final @NonNull Event event,
final @NonNull Consumer<ScopedSystemTransaction<StateSignatureTransaction>>
stateSignatureTransactionCallback) {
try {
final var stateSignatureTransaction =
StateSignatureTransaction.PROTOBUF.parse(transaction.getApplicationTransaction());
stateSignatureTransactionCallback.accept(new ScopedSystemTransaction<>(
event.getCreatorId(), event.getSoftwareVersion(), stateSignatureTransaction));
} catch (final ParseException e) {
logger.error("Failed to parse StateSignatureTransaction", e);

Check warning on line 380 in platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java

View check run for this annotation

Codecov / codecov/patch

platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java#L379-L380

Added lines #L379 - L380 were not covered by tests
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2024 Hedera Hashgraph, LLC
* Copyright (C) 2022-2025 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -59,6 +59,8 @@ public byte[] generateTransaction() throws SignatureException {
final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
final SerializableDataOutputStream out = new SerializableDataOutputStream(byteOut);
try {
// Adding additional byte to differentiate application transactions from system ones
out.write(1);
mustafauzunn marked this conversation as resolved.
Show resolved Hide resolved
out.writeSerializable(transaction, false);
} catch (final IOException e) {
throw new UncheckedIOException(e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
* Copyright (C) 2024-2025 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -26,16 +26,25 @@
* Utility methods for migration testing tool transactions
*/
public class TransactionUtils {
private static final byte APPLICATION_TRANSACTION_MARKER = 1;

/**
* Parse a {@link MigrationTestingToolTransaction} from a {@link Bytes}.
*/
public static @NonNull MigrationTestingToolTransaction parseTransaction(@NonNull final Bytes bytes) {
final SerializableDataInputStream in = new SerializableDataInputStream(bytes.toInputStream());
// Remove the first byte, which is marker added to distinguish application transactions from system ones in
// TransactionGenerator
final Bytes slicedBytes = bytes.slice(1, bytes.length() - 1);
final SerializableDataInputStream in = new SerializableDataInputStream(slicedBytes.toInputStream());

try {
return in.readSerializable(false, MigrationTestingToolTransaction::new);
} catch (final IOException e) {
throw new UncheckedIOException("Could not parse transaction kind:%s".formatted(bytes.toHex()), e);
}
}

public static boolean isSystemTransaction(@NonNull final Bytes bytes) {
return bytes.getByte(0) != APPLICATION_TRANSACTION_MARKER;
}
}
Loading