diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/merkle/MerkleSchemaRegistry.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/merkle/MerkleSchemaRegistry.java
index bc6461b3c283..680a45d34053 100644
--- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/merkle/MerkleSchemaRegistry.java
+++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/merkle/MerkleSchemaRegistry.java
@@ -22,6 +22,7 @@
import static com.hedera.node.app.state.merkle.VersionUtils.alreadyIncludesStateDefs;
import static com.hedera.node.app.state.merkle.VersionUtils.isSoOrdered;
import static com.hedera.node.app.workflows.handle.metric.UnavailableMetrics.UNAVAILABLE_METRICS;
+import static com.swirlds.state.merkle.StateUtils.registerWithSystem;
import static java.util.Objects.requireNonNull;
import com.hedera.hapi.node.base.SemanticVersion;
@@ -31,9 +32,7 @@
import com.hedera.node.app.services.MigrationStateChanges;
import com.hedera.node.app.spi.state.FilteredReadableStates;
import com.hedera.node.app.spi.state.FilteredWritableStates;
-import com.swirlds.common.constructable.ClassConstructorPair;
import com.swirlds.common.constructable.ConstructableRegistry;
-import com.swirlds.common.constructable.ConstructableRegistryException;
import com.swirlds.common.crypto.DigestType;
import com.swirlds.config.api.Configuration;
import com.swirlds.merkle.map.MerkleMap;
@@ -51,16 +50,10 @@
import com.swirlds.state.lifecycle.info.NetworkInfo;
import com.swirlds.state.merkle.StateMetadata;
import com.swirlds.state.merkle.StateUtils;
-import com.swirlds.state.merkle.disk.OnDiskKey;
import com.swirlds.state.merkle.disk.OnDiskKeySerializer;
-import com.swirlds.state.merkle.disk.OnDiskValue;
import com.swirlds.state.merkle.disk.OnDiskValueSerializer;
-import com.swirlds.state.merkle.memory.InMemoryValue;
-import com.swirlds.state.merkle.memory.InMemoryWritableKVState;
import com.swirlds.state.merkle.queue.QueueNode;
import com.swirlds.state.merkle.singleton.SingletonNode;
-import com.swirlds.state.merkle.singleton.StringLeaf;
-import com.swirlds.state.merkle.singleton.ValueLeaf;
import com.swirlds.state.spi.WritableStates;
import com.swirlds.virtualmap.VirtualMap;
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -151,7 +144,7 @@ public SchemaRegistry register(@NonNull Schema schema) {
schema.statesToCreate(bootstrapConfig).forEach(def -> {
//noinspection rawtypes,unchecked
final var md = new StateMetadata<>(serviceName, schema, def);
- registerWithSystem(md);
+ registerWithSystem(md, constructableRegistry);
});
return this;
@@ -380,81 +373,4 @@ private RedefinedWritableStates applyStateDefinitions(
final var newStates = new FilteredWritableStates(writableStates, remainingStates);
return new RedefinedWritableStates(writableStates, newStates);
}
-
- /**
- * Registers with the {@link ConstructableRegistry} system a class ID and a class. While this
- * will only be used for in-memory states, it is safe to register for on-disk ones as well.
- *
- *
The implementation will take the service name and the state key and compute a hash for it.
- * It will then convert the hash to a long, and use that as the class ID. It will then register
- * an {@link InMemoryWritableKVState}'s value merkle type to be deserialized, answering with the
- * generated class ID.
- *
- * @param md The state metadata
- */
- @SuppressWarnings({"rawtypes", "unchecked"})
- private void registerWithSystem(@NonNull final StateMetadata md) {
- // Register with the system the uniqueId as the "classId" of an InMemoryValue. There can be
- // multiple id's associated with InMemoryValue. The secret is that the supplier captures the
- // various delegate writers and parsers, and so can parse/write different types of data
- // based on the id.
- try {
- constructableRegistry.registerConstructable(new ClassConstructorPair(
- InMemoryValue.class,
- () -> new InMemoryValue(
- md.inMemoryValueClassId(),
- md.stateDefinition().keyCodec(),
- md.stateDefinition().valueCodec())));
- constructableRegistry.registerConstructable(new ClassConstructorPair(
- OnDiskKey.class,
- () -> new OnDiskKey<>(
- md.onDiskKeyClassId(), md.stateDefinition().keyCodec())));
- constructableRegistry.registerConstructable(new ClassConstructorPair(
- OnDiskKeySerializer.class,
- () -> new OnDiskKeySerializer<>(
- md.onDiskKeySerializerClassId(),
- md.onDiskKeyClassId(),
- md.stateDefinition().keyCodec())));
- constructableRegistry.registerConstructable(new ClassConstructorPair(
- OnDiskValue.class,
- () -> new OnDiskValue<>(
- md.onDiskValueClassId(), md.stateDefinition().valueCodec())));
- constructableRegistry.registerConstructable(new ClassConstructorPair(
- OnDiskValueSerializer.class,
- () -> new OnDiskValueSerializer<>(
- md.onDiskValueSerializerClassId(),
- md.onDiskValueClassId(),
- md.stateDefinition().valueCodec())));
- constructableRegistry.registerConstructable(new ClassConstructorPair(
- SingletonNode.class,
- () -> new SingletonNode<>(
- md.serviceName(),
- md.stateDefinition().stateKey(),
- md.singletonClassId(),
- md.stateDefinition().valueCodec(),
- null)));
- constructableRegistry.registerConstructable(new ClassConstructorPair(
- QueueNode.class,
- () -> new QueueNode<>(
- md.serviceName(),
- md.stateDefinition().stateKey(),
- md.queueNodeClassId(),
- md.singletonClassId(),
- md.stateDefinition().valueCodec())));
- constructableRegistry.registerConstructable(new ClassConstructorPair(StringLeaf.class, StringLeaf::new));
- constructableRegistry.registerConstructable(new ClassConstructorPair(
- ValueLeaf.class,
- () -> new ValueLeaf<>(
- md.singletonClassId(), md.stateDefinition().valueCodec())));
- } catch (ConstructableRegistryException e) {
- // This is a fatal error.
- throw new IllegalStateException(
- "Failed to register with the system '"
- + serviceName
- + ":"
- + md.stateDefinition().stateKey()
- + "'",
- e);
- }
- }
}
diff --git a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoMain.java b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoMain.java
index 28e21828fb5b..d6de55759f65 100644
--- a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoMain.java
+++ b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoMain.java
@@ -36,11 +36,11 @@
import com.swirlds.common.utility.AutoCloseableWrapper;
import com.swirlds.metrics.api.Metrics;
import com.swirlds.platform.Browser;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
@@ -182,9 +182,11 @@ public void run() {
@Override
@NonNull
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new CryptocurrencyDemoState());
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new CryptocurrencyDemoState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(softwareVersion.getSoftwareVersion()));
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
return state;
}
diff --git a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoState.java b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoState.java
index d08785a13640..8225e5ba318f 100644
--- a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoState.java
+++ b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoState.java
@@ -26,25 +26,23 @@
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
+import com.hedera.hapi.node.base.SemanticVersion;
import com.hedera.pbj.runtime.io.buffer.Bytes;
-import com.swirlds.common.io.streams.SerializableDataInputStream;
-import com.swirlds.common.io.streams.SerializableDataOutputStream;
-import com.swirlds.common.merkle.MerkleLeaf;
-import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
+import com.swirlds.common.constructable.ConstructableIgnored;
import com.swirlds.common.platform.NodeId;
import com.swirlds.platform.SwirldsPlatform;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
import com.swirlds.platform.system.InitTrigger;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.Round;
import com.swirlds.platform.system.SoftwareVersion;
-import com.swirlds.platform.system.SwirldState;
import com.swirlds.platform.system.address.Address;
import com.swirlds.platform.system.address.AddressBook;
import com.swirlds.platform.system.transaction.Transaction;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -52,6 +50,7 @@
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
/**
* This holds the current state of a swirld representing both a cryptocurrency and a stock market.
@@ -62,7 +61,8 @@
* entirely new cryptocurrency is created every time all the computers start the program over again, so
* these cryptocurrencies won't have any actual value.
*/
-public class CryptocurrencyDemoState extends PartialMerkleLeaf implements SwirldState, MerkleLeaf {
+@ConstructableIgnored
+public class CryptocurrencyDemoState extends MerkleStateRoot {
/**
* The version history of this class.
@@ -134,7 +134,11 @@ public static enum TransType {
////////////////////////////////////////////////////
- public CryptocurrencyDemoState() {}
+ public CryptocurrencyDemoState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory) {
+ super(lifecycles, versionFactory);
+ }
private CryptocurrencyDemoState(final CryptocurrencyDemoState sourceState) {
super(sourceState);
@@ -196,6 +200,7 @@ public synchronized long getNumTrades() {
@Override
public synchronized CryptocurrencyDemoState copy() {
throwIfImmutable();
+ setImmutable(true);
return new CryptocurrencyDemoState(this);
}
@@ -380,76 +385,14 @@ public void init(
@NonNull final Platform platform,
@NonNull final InitTrigger trigger,
@Nullable final SoftwareVersion previousSoftwareVersion) {
- this.platform = (SwirldsPlatform) platform;
+ super.init(platform, trigger, previousSoftwareVersion);
+ this.platform = (SwirldsPlatform) platform;
if (trigger == InitTrigger.GENESIS) {
genesisInit();
}
}
- @Override
- public void serialize(final SerializableDataOutputStream out) throws IOException {
- out.writeStringArray(tickerSymbol);
-
- out.writeInt(wallet.size());
- for (Map.Entry entry : wallet.entrySet()) {
- out.writeSerializable(entry.getKey(), false);
- out.writeLong(entry.getValue().get());
- }
-
- out.writeInt(shares.size());
- for (Map.Entry> entry : shares.entrySet()) {
- out.writeSerializable(entry.getKey(), false);
- out.writeInt(entry.getValue().size());
- for (int i = 0; i < entry.getValue().size(); i++) {
- out.writeLong(entry.getValue().get(i).get());
- }
- }
-
- out.writeStringArray(trades);
- out.writeInt(numTradesStored);
- out.writeInt(lastTradeIndex);
- out.writeLong(numTrades);
- out.writeByteArray(ask);
- out.writeByteArray(bid);
- out.writeSerializableArray(askId, false, true);
- out.writeSerializableArray(bidId, false, true);
- out.writeByteArray(price);
- }
-
- @Override
- public void deserialize(final SerializableDataInputStream in, final int version) throws IOException {
- tickerSymbol = in.readStringArray(DEFAULT_MAX_ARRAY_SIZE, DEFAULT_MAX_STRING_SIZE);
-
- int walletSize = in.readInt();
- for (int i = 0; i < walletSize; i++) {
- final NodeId id = in.readSerializable(false, NodeId::new);
- final AtomicLong amount = new AtomicLong(in.readLong());
- wallet.put(id, amount);
- }
-
- final int sharesSize = in.readInt();
- for (int i = 0; i < sharesSize; i++) {
- final NodeId id = in.readSerializable(false, NodeId::new);
- final int numShares = in.readInt();
- final List sharesForID = new ArrayList<>(numShares);
- for (int j = 0; j < numShares; j++) {
- sharesForID.add(new AtomicLong(in.readLong()));
- }
- shares.put(id, sharesForID);
- }
-
- trades = in.readStringArray(DEFAULT_MAX_ARRAY_SIZE, DEFAULT_MAX_STRING_SIZE);
- numTradesStored = in.readInt();
- lastTradeIndex = in.readInt();
- numTrades = in.readLong();
- ask = in.readByteArray(DEFAULT_MAX_ARRAY_SIZE);
- bid = in.readByteArray(DEFAULT_MAX_ARRAY_SIZE);
- askId = in.readSerializableArray(NodeId[]::new, DEFAULT_MAX_ARRAY_SIZE, false, NodeId::new);
- bidId = in.readSerializableArray(NodeId[]::new, DEFAULT_MAX_ARRAY_SIZE, false, NodeId::new);
- price = in.readByteArray(DEFAULT_MAX_ARRAY_SIZE);
- }
-
@Override
public long getClassId() {
return CLASS_ID;
diff --git a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/module-info.java b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/module-info.java
index b42efa99b26b..769d0e16696f 100644
--- a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/module-info.java
@@ -1,7 +1,9 @@
module com.swirlds.demo.crypto {
+ requires com.hedera.node.hapi;
requires com.swirlds.common;
requires com.swirlds.metrics.api;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
requires com.hedera.pbj.runtime;
requires java.desktop;
requires static com.github.spotbugs.annotations;
diff --git a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoMain.java b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoMain.java
index 04dfe21cdf2a..236de5ca7703 100644
--- a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoMain.java
+++ b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoMain.java
@@ -35,12 +35,12 @@
import com.swirlds.platform.SwirldsPlatform;
import com.swirlds.platform.listeners.PlatformStatusChangeListener;
import com.swirlds.platform.listeners.PlatformStatusChangeNotification;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
import com.swirlds.platform.system.status.PlatformStatus;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.nio.charset.StandardCharsets;
@@ -109,9 +109,11 @@ public void run() {
@NonNull
@Override
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new HelloSwirldDemoState());
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new HelloSwirldDemoState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(softwareVersion.getSoftwareVersion()));
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
return state;
}
diff --git a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoState.java b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoState.java
index 7d36ec7950cd..9ac33b259c35 100644
--- a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoState.java
+++ b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoState.java
@@ -26,25 +26,27 @@
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
-import com.swirlds.common.io.streams.SerializableDataInputStream;
-import com.swirlds.common.io.streams.SerializableDataOutputStream;
-import com.swirlds.common.merkle.MerkleLeaf;
-import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
+import com.hedera.hapi.node.base.SemanticVersion;
+import com.swirlds.common.constructable.ConstructableIgnored;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
import com.swirlds.platform.system.Round;
-import com.swirlds.platform.system.SwirldState;
+import com.swirlds.platform.system.SoftwareVersion;
import com.swirlds.platform.system.transaction.Transaction;
-import java.io.IOException;
+import edu.umd.cs.findbugs.annotations.NonNull;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Function;
/**
* This holds the current state of the swirld. For this simple "hello swirld" code, each transaction is just
* a string, and the state is just a list of the strings in all the transactions handled so far, in the
* order that they were handled.
*/
-public class HelloSwirldDemoState extends PartialMerkleLeaf implements SwirldState, MerkleLeaf {
+@ConstructableIgnored
+public class HelloSwirldDemoState extends MerkleStateRoot {
/**
* The version history of this class.
@@ -91,7 +93,11 @@ public synchronized String toString() {
// ///////////////////////////////////////////////////////////////////
- public HelloSwirldDemoState() {}
+ public HelloSwirldDemoState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory) {
+ super(lifecycles, versionFactory);
+ }
private HelloSwirldDemoState(final HelloSwirldDemoState sourceState) {
super(sourceState);
@@ -107,6 +113,7 @@ public synchronized void handleConsensusRound(final Round round, final PlatformS
@Override
public synchronized HelloSwirldDemoState copy() {
throwIfImmutable();
+ setImmutable(true);
return new HelloSwirldDemoState(this);
}
@@ -117,16 +124,6 @@ private void handleTransaction(final Transaction transaction) {
strings.add(new String(transaction.getApplicationTransaction().toByteArray(), StandardCharsets.UTF_8));
}
- @Override
- public void serialize(final SerializableDataOutputStream out) throws IOException {
- out.writeStringList(strings);
- }
-
- @Override
- public void deserialize(final SerializableDataInputStream in, final int version) throws IOException {
- strings = in.readStringList(DEFAULT_MAX_ARRAY_SIZE, DEFAULT_MAX_STRING_SIZE);
- }
-
@Override
public long getClassId() {
return CLASS_ID;
diff --git a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/module-info.java b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/module-info.java
index cfd02e9373bc..76f2cb141a2c 100644
--- a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/module-info.java
@@ -1,6 +1,8 @@
module com.swirlds.demo.hello {
+ requires com.hedera.node.hapi;
requires com.swirlds.common;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
requires com.hedera.pbj.runtime;
requires java.desktop;
requires static com.github.spotbugs.annotations;
diff --git a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoMain.java b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoMain.java
index 794f67e901c1..27a7cb63063b 100644
--- a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoMain.java
+++ b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoMain.java
@@ -39,11 +39,11 @@
import com.swirlds.metrics.api.Metrics;
import com.swirlds.platform.Browser;
import com.swirlds.platform.ParameterProvider;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.BufferedWriter;
import java.io.File;
@@ -297,9 +297,11 @@ private String valueAsString(final Metric metric) {
@NonNull
@Override
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new StatsDemoState());
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new StatsDemoState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(softwareVersion.getSoftwareVersion()));
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
return state;
}
diff --git a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoState.java b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoState.java
index 68d018b2c2a3..dc4662f77807 100644
--- a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoState.java
+++ b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoState.java
@@ -26,13 +26,15 @@
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
-import com.swirlds.common.io.streams.SerializableDataInputStream;
-import com.swirlds.common.io.streams.SerializableDataOutputStream;
-import com.swirlds.common.merkle.MerkleLeaf;
-import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
+import com.hedera.hapi.node.base.SemanticVersion;
+import com.swirlds.common.constructable.ConstructableIgnored;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
import com.swirlds.platform.system.Round;
-import com.swirlds.platform.system.SwirldState;
+import com.swirlds.platform.system.SoftwareVersion;
+import edu.umd.cs.findbugs.annotations.NonNull;
+import java.util.function.Function;
/**
* This demo collects statistics on the running of the network and consensus systems. It writes them to the
@@ -41,7 +43,8 @@
* is 100 random bytes. So StatsDemoState.handleTransaction doesn't actually do anything, other than the
* optional sequence number check.
*/
-public class StatsDemoState extends PartialMerkleLeaf implements SwirldState, MerkleLeaf {
+@ConstructableIgnored
+public class StatsDemoState extends MerkleStateRoot {
/**
* The version history of this class.
@@ -62,7 +65,11 @@ private static class ClassVersion {
private static final long CLASS_ID = 0xc550a1cd94e91ca3L;
- public StatsDemoState() {}
+ public StatsDemoState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory) {
+ super(lifecycles, versionFactory);
+ }
private StatsDemoState(final StatsDemoState sourceState) {
super(sourceState);
@@ -77,21 +84,10 @@ public void handleConsensusRound(final Round round, final PlatformStateModifier
@Override
public synchronized StatsDemoState copy() {
throwIfImmutable();
+ setImmutable(true);
return new StatsDemoState(this);
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void serialize(final SerializableDataOutputStream out) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void deserialize(final SerializableDataInputStream in, final int version) {}
-
/**
* {@inheritDoc}
*/
diff --git a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/module-info.java b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/module-info.java
index e0830b328858..5387a8dc5903 100644
--- a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/module-info.java
@@ -1,8 +1,10 @@
module com.swirlds.demo.stats {
+ requires com.hedera.node.hapi;
requires com.swirlds.base;
requires com.swirlds.common;
requires com.swirlds.metrics.api;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
requires java.desktop;
requires static com.github.spotbugs.annotations;
}
diff --git a/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolMain.java b/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolMain.java
index 8fef0db4e50a..eff2c97441d2 100644
--- a/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolMain.java
+++ b/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolMain.java
@@ -23,11 +23,11 @@
import com.swirlds.config.api.Configuration;
import com.swirlds.config.api.ConfigurationBuilder;
import com.swirlds.platform.config.DefaultConfiguration;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.io.IOException;
@@ -105,9 +105,11 @@ public void run() {
*/
@Override
@NonNull
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new AddressBookTestingToolState());
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new AddressBookTestingToolState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(softwareVersion.getSoftwareVersion()));
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
return state;
}
diff --git a/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolState.java b/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolState.java
index 29a02aa8a2e2..f10d931a37ea 100644
--- a/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolState.java
+++ b/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/com/swirlds/demo/addressbook/AddressBookTestingToolState.java
@@ -35,25 +35,23 @@
import static com.swirlds.platform.state.address.AddressBookInitializer.STATE_ADDRESS_BOOK_USED;
import static com.swirlds.platform.state.address.AddressBookInitializer.USED_ADDRESS_BOOK_HEADER;
+import com.hedera.hapi.node.base.SemanticVersion;
import com.hedera.hapi.node.state.roster.Roster;
import com.hedera.pbj.runtime.io.buffer.Bytes;
+import com.swirlds.common.constructable.ConstructableIgnored;
import com.swirlds.common.context.PlatformContext;
-import com.swirlds.common.io.streams.SerializableDataInputStream;
-import com.swirlds.common.io.streams.SerializableDataOutputStream;
-import com.swirlds.common.merkle.MerkleLeaf;
-import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
import com.swirlds.common.platform.NodeId;
import com.swirlds.common.utility.ByteUtils;
import com.swirlds.common.utility.StackTrace;
import com.swirlds.platform.config.AddressBookConfig;
import com.swirlds.platform.roster.RosterRetriever;
-import com.swirlds.platform.state.PlatformStateAccessor;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
import com.swirlds.platform.system.InitTrigger;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.Round;
import com.swirlds.platform.system.SoftwareVersion;
-import com.swirlds.platform.system.SwirldState;
import com.swirlds.platform.system.address.Address;
import com.swirlds.platform.system.address.AddressBook;
import com.swirlds.platform.system.address.AddressBookUtils;
@@ -71,13 +69,15 @@
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* State for the AddressBookTestingTool.
*/
-public class AddressBookTestingToolState extends PartialMerkleLeaf implements SwirldState, MerkleLeaf {
+@ConstructableIgnored
+public class AddressBookTestingToolState extends MerkleStateRoot {
private static final Logger logger = LogManager.getLogger(AddressBookTestingToolState.class);
@@ -113,8 +113,8 @@ private static class ClassVersion {
/**
* The number of rounds handled by this app. Is incremented each time
- * {@link #handleConsensusRound(Round, PlatformStateAccessor)} is called. Note that this may not actually equal the round
- * number, since we don't call {@link #handleConsensusRound(Round, PlatformStateAccessor)} for rounds with no events.
+ * {@link #handleConsensusRound(Round, PlatformStateModifier)} is called. Note that this may not actually equal the round
+ * number, since we don't call {@link #handleConsensusRound(Round, PlatformStateModifier)} for rounds with no events.
*
*
* Affects the hash of this node.
@@ -129,7 +129,10 @@ private static class ClassVersion {
*/
private Duration freezeAfterGenesis = null;
- public AddressBookTestingToolState() {
+ public AddressBookTestingToolState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory) {
+ super(lifecycles, versionFactory);
logger.info(STARTUP.getMarker(), "New State Constructed.");
}
@@ -156,6 +159,7 @@ private AddressBookTestingToolState(@NonNull final AddressBookTestingToolState t
@Override
public synchronized AddressBookTestingToolState copy() {
throwIfImmutable();
+ setImmutable(true);
return new AddressBookTestingToolState(this);
}
@@ -233,26 +237,6 @@ private void handleTransaction(@NonNull final ConsensusTransaction transaction)
runningSum += delta;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void serialize(@NonNull final SerializableDataOutputStream out) throws IOException {
- Objects.requireNonNull(out, "the serializable data output stream cannot be null");
- out.writeLong(runningSum);
- out.writeLong(roundsHandled);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void deserialize(@NonNull final SerializableDataInputStream in, final int version) throws IOException {
- Objects.requireNonNull(in, "the serializable data input stream cannot be null");
- runningSum = in.readLong();
- roundsHandled = in.readLong();
- }
-
/**
* {@inheritDoc}
*/
diff --git a/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/module-info.java b/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/module-info.java
index 814c35531ef9..dc767113b793 100644
--- a/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/tests/AddressBookTestingTool/src/main/java/module-info.java
@@ -5,6 +5,7 @@
requires com.swirlds.config.api;
requires com.swirlds.logging;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
requires com.hedera.pbj.runtime;
requires org.apache.logging.log4j;
requires static com.github.spotbugs.annotations;
diff --git a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/build.gradle.kts b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/build.gradle.kts
index 75324db7df15..0cb0449462f1 100644
--- a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/build.gradle.kts
+++ b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/build.gradle.kts
@@ -21,7 +21,6 @@ application.mainClass.set("com.swirlds.demo.consistency.ConsistencyTestingToolMa
mainModuleInfo { annotationProcessor("com.swirlds.config.processor") }
testModuleInfo {
- requires("com.hedera.node.hapi")
requires("com.swirlds.common.test.fixtures")
requires("com.swirlds.platform.core.test.fixtures")
requires("org.junit.jupiter.api")
diff --git a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolMain.java b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolMain.java
index 1f197fc14865..4ba378f469f9 100644
--- a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolMain.java
+++ b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolMain.java
@@ -17,14 +17,22 @@
package com.swirlds.demo.consistency;
import static com.swirlds.logging.legacy.LogMarker.STARTUP;
+import static com.swirlds.platform.util.NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES;
+import static com.swirlds.state.merkle.StateUtils.registerWithSystem;
+import com.swirlds.common.constructable.ClassConstructorPair;
+import com.swirlds.common.constructable.ConstructableRegistry;
+import com.swirlds.common.constructable.ConstructableRegistryException;
import com.swirlds.common.platform.NodeId;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
+import com.swirlds.platform.state.service.PlatformStateService;
+import com.swirlds.platform.state.service.schemas.V0540PlatformStateSchema;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SoftwareVersion;
import com.swirlds.platform.system.SwirldMain;
+import com.swirlds.state.lifecycle.StateDefinition;
+import com.swirlds.state.merkle.StateMetadata;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.security.SecureRandom;
@@ -45,6 +53,31 @@ public class ConsistencyTestingToolMain implements SwirldMain {
*/
private static final SoftwareVersion softwareVersion = new BasicSoftwareVersion(1);
+ static {
+ try {
+ logger.info(STARTUP.getMarker(), "Registering ConsistencyTestingToolState with ConstructableRegistry");
+ ConstructableRegistry constructableRegistry = ConstructableRegistry.getInstance();
+ constructableRegistry.registerConstructable(new ClassConstructorPair(
+ ConsistencyTestingToolState.class,
+ () -> new ConsistencyTestingToolState(
+ NO_OP_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(version.major()))));
+ logger.info(STARTUP.getMarker(), "ConsistencyTestingToolState is registered with ConstructableRegistry");
+ registerPlatformClasses(constructableRegistry);
+
+ } catch (ConstructableRegistryException e) {
+ logger.error(STARTUP.getMarker(), "Failed to register ConsistencyTestingToolState", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void registerPlatformClasses(ConstructableRegistry constructableRegistry) {
+ logger.info(STARTUP.getMarker(), "Registering PlatformState classes with ConstructableRegistry");
+ final var schema = new V0540PlatformStateSchema();
+ final StateDefinition def = schema.statesToCreate().iterator().next();
+ final var md = new StateMetadata<>(PlatformStateService.NAME, schema, def);
+ registerWithSystem(md, constructableRegistry);
+ }
+
/**
* The platform instance
*/
@@ -88,9 +121,12 @@ public void run() {
*/
@Override
@NonNull
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new ConsistencyTestingToolState());
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new ConsistencyTestingToolState(
+ NO_OP_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(softwareVersion.getVersion()));
+ NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
+ registerPlatformClasses(ConstructableRegistry.INSTANCE);
+
return state;
}
diff --git a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolRound.java b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolRound.java
index f1df5c5a342a..e3ff72b2257f 100644
--- a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolRound.java
+++ b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolRound.java
@@ -25,6 +25,8 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
/**
* Represents a round in the ConsistencyTestingTool
@@ -36,6 +38,8 @@
public record ConsistencyTestingToolRound(long roundNumber, long currentState, @NonNull List transactionsContents)
implements Comparable {
+ private static final Logger logger = LogManager.getLogger(ConsistencyTestingToolRound.class);
+
private static final String ROUND_NUMBER_STRING = "Round Number: ";
private static final String CURRENT_STATE_STRING = "Current State: ";
private static final String TRANSACTIONS_STRING = "Transactions: ";
diff --git a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolState.java b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolState.java
index 4cbd7b6c7b7b..23704fbcbc29 100644
--- a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolState.java
+++ b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolState.java
@@ -19,22 +19,22 @@
import static com.swirlds.common.utility.ByteUtils.byteArrayToLong;
import static com.swirlds.logging.legacy.LogMarker.EXCEPTION;
import static com.swirlds.logging.legacy.LogMarker.STARTUP;
+import static com.swirlds.platform.util.NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES;
+import com.hedera.hapi.node.base.SemanticVersion;
import com.swirlds.common.config.StateCommonConfig;
-import com.swirlds.common.io.streams.SerializableDataInputStream;
-import com.swirlds.common.io.streams.SerializableDataOutputStream;
-import com.swirlds.common.merkle.MerkleLeaf;
-import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
+import com.swirlds.common.constructable.ConstructableIgnored;
import com.swirlds.common.utility.NonCryptographicHashing;
-import com.swirlds.platform.state.PlatformStateAccessor;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
import com.swirlds.platform.system.InitTrigger;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.Round;
import com.swirlds.platform.system.SoftwareVersion;
-import com.swirlds.platform.system.SwirldState;
import com.swirlds.platform.system.events.Event;
import com.swirlds.platform.system.transaction.ConsensusTransaction;
+import com.swirlds.state.merkle.singleton.StringLeaf;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.io.IOException;
@@ -45,13 +45,15 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* State for the Consistency Testing Tool
*/
-public class ConsistencyTestingToolState extends PartialMerkleLeaf implements SwirldState, MerkleLeaf {
+@ConstructableIgnored
+public class ConsistencyTestingToolState extends MerkleStateRoot {
private static final Logger logger = LogManager.getLogger(ConsistencyTestingToolState.class);
private static final long CLASS_ID = 0xda03bb07eb897d82L;
@@ -59,6 +61,9 @@ private static class ClassVersion {
public static final int ORIGINAL = 1;
}
+ private static final int STATE_LONG_INDEX = 1;
+ private static final int ROUND_HANDLED_INDEX = 2;
+
/**
* The history of transactions that have been handled by this app.
*
@@ -70,14 +75,14 @@ private static class ClassVersion {
/**
* The true "state" of this app. This long value is updated with every transaction, and with every round.
*
- * Effects the hash of this node.
+ * Affects the hash of this node.
*/
private long stateLong = 0;
/**
* The number of rounds handled by this app. Is incremented each time
- * {@link #handleConsensusRound(Round, PlatformStateAccessor)} is called. Note that this may not actually equal the round
- * number, since we don't call {@link #handleConsensusRound(Round, PlatformStateAccessor)} for rounds with no events.
+ * {@link #handleConsensusRound(Round, PlatformStateModifier)} is called. Note that this may not actually equal the round
+ * number, since we don't call {@link #handleConsensusRound(Round, PlatformStateModifier)} for rounds with no events.
*
*
* Affects the hash of this node.
@@ -104,7 +109,10 @@ private static class ClassVersion {
/**
* Constructor
*/
- public ConsistencyTestingToolState() {
+ public ConsistencyTestingToolState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory) {
+ super(lifecycles, versionFactory);
logger.info(STARTUP.getMarker(), "New State Constructed.");
this.transactionHandlingHistory = new TransactionHandlingHistory();
@@ -155,7 +163,19 @@ public void init(
this.freezeAfterGenesis = testingToolConfig.freezeAfterGenesis();
+ final StringLeaf stateLongLeaf = getChild(STATE_LONG_INDEX);
+ if (stateLongLeaf != null && stateLongLeaf.getLabel() != null) {
+ this.stateLong = Long.parseLong(stateLongLeaf.getLabel());
+ logger.info(STARTUP.getMarker(), "State initialized with state long {}.", stateLong);
+ }
+ final StringLeaf roundsHandledLeaf = getChild(ROUND_HANDLED_INDEX);
+ if (roundsHandledLeaf != null && roundsHandledLeaf.getLabel() != null) {
+ this.roundsHandled = Long.parseLong(roundsHandledLeaf.getLabel());
+ logger.info(STARTUP.getMarker(), "State initialized with {} rounds handled.", roundsHandled);
+ }
+
transactionHandlingHistory.init(logFilePath);
+ NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(this);
}
/**
@@ -170,26 +190,15 @@ public long getClassId() {
* {@inheritDoc}
*/
@Override
- public void serialize(final @NonNull SerializableDataOutputStream out) throws IOException {
- Objects.requireNonNull(out);
- out.writeLong(stateLong);
- out.writeLong(roundsHandled);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void deserialize(final @NonNull SerializableDataInputStream in, final int version) throws IOException {
- stateLong = Objects.requireNonNull(in).readLong();
- roundsHandled = in.readLong();
+ public int getVersion() {
+ return ClassVersion.ORIGINAL;
}
/**
* {@inheritDoc}
*/
@Override
- public int getVersion() {
+ public int getMinimumSupportedVersion() {
return ClassVersion.ORIGINAL;
}
@@ -200,6 +209,7 @@ public int getVersion() {
@NonNull
public synchronized ConsistencyTestingToolState copy() {
throwIfImmutable();
+ setImmutable(true);
return new ConsistencyTestingToolState(this);
}
@@ -269,5 +279,8 @@ public void handleConsensusRound(final @NonNull Round round, final @NonNull Plat
stateLong = NonCryptographicHashing.hash64(stateLong, round.getRoundNum());
transactionHandlingHistory.processRound(ConsistencyTestingToolRound.fromRound(round, stateLong));
+
+ setChild(ROUND_HANDLED_INDEX, new StringLeaf(Long.toString(roundsHandled)));
+ setChild(STATE_LONG_INDEX, new StringLeaf(Long.toString(stateLong)));
}
}
diff --git a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/module-info.java b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/module-info.java
index be312e2cff34..c525c555dc08 100644
--- a/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/module-info.java
@@ -1,9 +1,12 @@
module com.swirlds.demo.consistency {
+ requires com.hedera.node.hapi;
requires com.swirlds.base;
requires com.swirlds.common;
requires com.swirlds.config.api;
requires com.swirlds.logging;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
+ requires com.swirlds.state.impl;
requires com.hedera.pbj.runtime;
requires org.apache.logging.log4j;
requires static com.github.spotbugs.annotations;
diff --git a/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolMain.java b/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolMain.java
index 1bd1ca3e790e..dcbe18542c62 100644
--- a/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolMain.java
+++ b/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolMain.java
@@ -19,13 +19,13 @@
import static com.swirlds.logging.legacy.LogMarker.STARTUP;
import com.swirlds.common.platform.NodeId;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
import com.swirlds.platform.system.state.notifications.IssListener;
import com.swirlds.platform.system.state.notifications.IssNotification;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.List;
@@ -89,9 +89,11 @@ public void run() {
*/
@Override
@NonNull
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new ISSTestingToolState());
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new ISSTestingToolState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(softwareVersion.getSoftwareVersion()));
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
return state;
}
diff --git a/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolState.java b/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolState.java
index 8c15be311f34..1e4e19e87a8f 100644
--- a/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolState.java
+++ b/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolState.java
@@ -32,27 +32,25 @@
import static com.swirlds.logging.legacy.LogMarker.EXCEPTION;
import static com.swirlds.logging.legacy.LogMarker.STARTUP;
+import com.hedera.hapi.node.base.SemanticVersion;
import com.hedera.hapi.node.state.roster.Roster;
import com.hedera.hapi.node.state.roster.RosterEntry;
-import com.swirlds.common.io.streams.SerializableDataInputStream;
-import com.swirlds.common.io.streams.SerializableDataOutputStream;
-import com.swirlds.common.merkle.MerkleLeaf;
-import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
+import com.swirlds.common.constructable.ConstructableIgnored;
import com.swirlds.common.merkle.utility.SerializableLong;
import com.swirlds.common.platform.NodeId;
import com.swirlds.common.utility.ByteUtils;
import com.swirlds.platform.scratchpad.Scratchpad;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
import com.swirlds.platform.system.InitTrigger;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.Round;
import com.swirlds.platform.system.SoftwareVersion;
-import com.swirlds.platform.system.SwirldState;
import com.swirlds.platform.system.events.ConsensusEvent;
import com.swirlds.platform.system.transaction.ConsensusTransaction;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
@@ -62,13 +60,15 @@
import java.util.Map;
import java.util.Objects;
import java.util.Random;
+import java.util.function.Function;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* State for the ISSTestingTool.
*/
-public class ISSTestingToolState extends PartialMerkleLeaf implements SwirldState, MerkleLeaf {
+@ConstructableIgnored
+public class ISSTestingToolState extends MerkleStateRoot {
private static final Logger logger = LogManager.getLogger(ISSTestingToolState.class);
@@ -110,7 +110,11 @@ private static class ClassVersion {
private Scratchpad scratchPad;
- public ISSTestingToolState() {}
+ public ISSTestingToolState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory) {
+ super(lifecycles, versionFactory);
+ }
/**
* Copy constructor.
@@ -140,6 +144,7 @@ public boolean isImmutable() {
@Override
public synchronized ISSTestingToolState copy() {
throwIfImmutable();
+ setImmutable(true);
return new ISSTestingToolState(this);
}
@@ -151,6 +156,7 @@ public void init(
@NonNull final Platform platform,
@NonNull final InitTrigger trigger,
@Nullable final SoftwareVersion previousSoftwareVersion) {
+ super.init(platform, trigger, previousSoftwareVersion);
throwIfImmutable();
@@ -391,28 +397,6 @@ private void triggerLogError(
elapsedSinceGenesis);
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void serialize(final SerializableDataOutputStream out) throws IOException {
- out.writeLong(runningSum);
- out.writeInstant(genesisTimestamp);
- out.writeSerializableList(plannedIssList, false, true);
- out.writeSerializableList(plannedLogErrorList, false, true);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void deserialize(final SerializableDataInputStream in, final int version) throws IOException {
- runningSum = in.readLong();
- genesisTimestamp = in.readInstant();
- plannedIssList = in.readSerializableList(1024, false, PlannedIss::new);
- plannedLogErrorList = in.readSerializableList(1024, false, PlannedLogError::new);
- }
-
/**
* {@inheritDoc}
*/
diff --git a/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/module-info.java b/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/module-info.java
index 4ddb608720bd..b621bdaab105 100644
--- a/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/module-info.java
@@ -5,6 +5,7 @@
requires com.swirlds.config.api;
requires com.swirlds.logging;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
requires com.hedera.pbj.runtime;
requires org.apache.logging.log4j;
requires static com.github.spotbugs.annotations;
diff --git a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java
index 8ac8ecb4e3d5..78959e527143 100644
--- a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java
+++ b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java
@@ -24,11 +24,11 @@
import com.swirlds.logging.legacy.payload.ApplicationFinishedPayload;
import com.swirlds.merkle.map.MerkleMapMetrics;
import com.swirlds.platform.ParameterProvider;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.security.SignatureException;
import org.apache.logging.log4j.LogManager;
@@ -166,9 +166,11 @@ private void throttleTransactionCreation() throws InterruptedException {
*/
@NonNull
@Override
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new MigrationTestingToolState());
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new MigrationTestingToolState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(softwareVersion.getSoftwareVersion()));
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
return state;
}
diff --git a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java
index da3a96b4f48b..af4b8cb98093 100644
--- a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java
+++ b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java
@@ -19,10 +19,10 @@
import static com.swirlds.demo.migration.MigrationTestingToolMain.PREVIOUS_SOFTWARE_VERSION;
import static com.swirlds.logging.legacy.LogMarker.STARTUP;
+import com.hedera.hapi.node.base.SemanticVersion;
+import com.swirlds.common.constructable.ConstructableIgnored;
import com.swirlds.common.crypto.DigestType;
-import com.swirlds.common.merkle.MerkleInternal;
import com.swirlds.common.merkle.MerkleNode;
-import com.swirlds.common.merkle.impl.PartialNaryMerkleInternal;
import com.swirlds.common.platform.NodeId;
import com.swirlds.config.api.Configuration;
import com.swirlds.config.api.ConfigurationBuilder;
@@ -35,12 +35,13 @@
import com.swirlds.merkledb.MerkleDbDataSourceBuilder;
import com.swirlds.merkledb.MerkleDbTableConfig;
import com.swirlds.merkledb.config.MerkleDbConfig;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
import com.swirlds.platform.system.InitTrigger;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.Round;
import com.swirlds.platform.system.SoftwareVersion;
-import com.swirlds.platform.system.SwirldState;
import com.swirlds.platform.system.address.AddressBook;
import com.swirlds.platform.system.events.ConsensusEvent;
import com.swirlds.platform.system.transaction.ConsensusTransaction;
@@ -50,10 +51,12 @@
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.Iterator;
import java.util.List;
+import java.util.function.Function;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-public class MigrationTestingToolState extends PartialNaryMerkleInternal implements MerkleInternal, SwirldState {
+@ConstructableIgnored
+public class MigrationTestingToolState extends MerkleStateRoot {
private static final Logger logger = LogManager.getLogger(MigrationTestingToolState.class);
/**
@@ -95,8 +98,11 @@ private static class ChildIndices {
public NodeId selfId;
- public MigrationTestingToolState() {
- super(ChildIndices.CHILD_COUNT);
+ public MigrationTestingToolState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory) {
+ super(lifecycles, versionFactory);
+ allocateSpaceForChild(ChildIndices.CHILD_COUNT);
}
private MigrationTestingToolState(final MigrationTestingToolState that) {
@@ -231,6 +237,8 @@ public void init(
@NonNull final Platform platform,
@NonNull final InitTrigger trigger,
@Nullable final SoftwareVersion previousSoftwareVersion) {
+ super.init(platform, trigger, previousSoftwareVersion);
+
final MerkleMap merkleMap = getMerkleMap();
if (merkleMap != null) {
logger.info(STARTUP.getMarker(), "MerkleMap initialized with {} values", merkleMap.size());
@@ -286,6 +294,7 @@ public void handleConsensusRound(final Round round, final PlatformStateModifier
@Override
public MigrationTestingToolState copy() {
throwIfImmutable();
+ setImmutable(true);
return new MigrationTestingToolState(this);
}
diff --git a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/module-info.java b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/module-info.java
index 51a47b50d856..167e8678b2f6 100644
--- a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/module-info.java
@@ -1,4 +1,5 @@
module com.swirlds.demo.migration {
+ requires com.hedera.node.hapi;
requires com.swirlds.base;
requires com.swirlds.common;
requires com.swirlds.config.api;
@@ -8,6 +9,7 @@
requires com.swirlds.merkledb;
requires com.swirlds.metrics.api;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
requires com.swirlds.virtualmap;
requires com.hedera.pbj.runtime;
requires java.logging;
diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/build.gradle.kts b/platform-sdk/platform-apps/tests/PlatformTestingTool/build.gradle.kts
index 5eddb4203445..e84c41fe4b1d 100644
--- a/platform-sdk/platform-apps/tests/PlatformTestingTool/build.gradle.kts
+++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/build.gradle.kts
@@ -44,6 +44,7 @@ timingSensitiveModuleInfo {
requires("com.swirlds.merkle")
requires("com.swirlds.merkle.test.fixtures")
requires("com.swirlds.platform.core")
+ requires("com.hedera.node.hapi")
requires("org.junit.jupiter.api")
requires("org.junit.jupiter.params")
requires("org.mockito")
diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PayloadCfgSimple.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PayloadCfgSimple.java
index 759054d4549f..4a45c94775a2 100644
--- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PayloadCfgSimple.java
+++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PayloadCfgSimple.java
@@ -23,9 +23,16 @@
import com.swirlds.common.merkle.MerkleLeaf;
import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
import java.io.IOException;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
public class PayloadCfgSimple extends PartialMerkleLeaf implements MerkleLeaf {
+ private static final Logger logger = LogManager.getLogger(PayloadCfgSimple.class);
+ private static final Marker LOGM_DEMO_INFO = MarkerManager.getMarker("DEMO_INFO");
+
/**
* The version history of this class.
* Versions that have been released must NEVER be given a different value.
@@ -160,10 +167,21 @@ private static class ClassVersion {
*/
private float ratioOfFCMTransaction;
- public PayloadCfgSimple() {}
+ public PayloadCfgSimple() {
+ // logger.info(
+ // LOGM_DEMO_INFO,
+ // "PayloadCfgSimple., immutable: {}, StackTrace: {}",
+ // isImmutable(),
+ // StackTrace.getStackTrace());
+ }
private PayloadCfgSimple(final PayloadCfgSimple sourcePayload) {
super(sourcePayload);
+ // logger.info(
+ // LOGM_DEMO_INFO,
+ // "PayloadCfgSimple.(COPY), immutable: {}, StackTrace: {}",
+ // isImmutable(),
+ // StackTrace.getStackTrace());
setAppendSig(sourcePayload.appendSig);
setInvalidSigRatio(sourcePayload.invalidSigRatio);
setInsertSeq(sourcePayload.insertSeq);
@@ -381,6 +399,11 @@ public void setRatioOfFCMTransaction(final float ratioOfFCMTransaction) {
*/
@Override
public PayloadCfgSimple copy() {
+ // logger.info(
+ // LOGM_DEMO_INFO,
+ // "PayloadCfgSimple.copy(), immutable: {}, StackTrace: {}",
+ // isImmutable(),
+ // StackTrace.getStackTrace());
throwIfImmutable();
return new PayloadCfgSimple(this);
}
diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolMain.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolMain.java
index e1847a320e8a..0f72ff44f8c6 100644
--- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolMain.java
+++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolMain.java
@@ -30,12 +30,14 @@
import static com.swirlds.common.threading.manager.AdHocThreadManager.getStaticThreadManager;
import static com.swirlds.logging.legacy.LogMarker.DEMO_INFO;
import static com.swirlds.logging.legacy.LogMarker.EXCEPTION;
+import static com.swirlds.logging.legacy.LogMarker.STARTUP;
import static com.swirlds.merkle.test.fixtures.map.lifecycle.EntityType.Crypto;
import static com.swirlds.merkle.test.fixtures.map.lifecycle.SaveExpectedMapHandler.STORAGE_DIRECTORY;
import static com.swirlds.merkle.test.fixtures.map.lifecycle.SaveExpectedMapHandler.createExpectedMapName;
import static com.swirlds.merkle.test.fixtures.map.lifecycle.SaveExpectedMapHandler.serialize;
import static com.swirlds.metrics.api.FloatFormats.FORMAT_6_2;
import static com.swirlds.metrics.api.FloatFormats.FORMAT_9_6;
+import static com.swirlds.state.merkle.StateUtils.registerWithSystem;
import static java.lang.System.exit;
import com.fasterxml.jackson.core.JsonParser;
@@ -43,6 +45,10 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.swirlds.base.units.UnitConstants;
import com.swirlds.base.utility.Pair;
+import com.swirlds.common.constructable.ClassConstructorPair;
+import com.swirlds.common.constructable.ConstructableRegistry;
+import com.swirlds.common.constructable.ConstructableRegistryException;
+import com.swirlds.common.constructable.NoArgsConstructor;
import com.swirlds.common.merkle.iterators.MerkleIterator;
import com.swirlds.common.metrics.RunningAverageMetric;
import com.swirlds.common.metrics.SpeedometerMetric;
@@ -79,8 +85,9 @@
import com.swirlds.platform.listeners.PlatformStatusChangeNotification;
import com.swirlds.platform.listeners.ReconnectCompleteListener;
import com.swirlds.platform.listeners.StateWriteToDiskCompleteListener;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
+import com.swirlds.platform.state.service.PlatformStateService;
+import com.swirlds.platform.state.service.schemas.V0540PlatformStateSchema;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
@@ -88,6 +95,9 @@
import com.swirlds.platform.system.SystemExitUtils;
import com.swirlds.platform.system.state.notifications.NewSignedStateListener;
import com.swirlds.platform.system.status.PlatformStatus;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
+import com.swirlds.state.lifecycle.StateDefinition;
+import com.swirlds.state.merkle.StateMetadata;
import com.swirlds.virtualmap.internal.merkle.VirtualLeafNode;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.File;
@@ -136,6 +146,39 @@ public class PlatformTestingToolMain implements SwirldMain {
private static final String FCM_CATEGORY = "FCM";
private static final String VM_CATEGORY = "VM";
+
+ static {
+ try {
+ logger.info(STARTUP.getMarker(), "Registering PlatformTestingToolState with ConstructableRegistry");
+ ConstructableRegistry.getInstance()
+ .registerConstructable(new ClassConstructorPair(
+ PlatformTestingToolState.class,
+ () -> new PlatformTestingToolState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(version.major()))));
+ logger.info(
+ STARTUP.getMarker(),
+ "PlatformTestingToolState is registered with ConstructableRegistry: {}",
+ ConstructableRegistry.getInstance()
+ .getRegistry(NoArgsConstructor.class)
+ .getConstructor(PlatformTestingToolState.CLASS_ID)
+ .get()
+ .getClassId());
+ registerPlatformClasses(ConstructableRegistry.getInstance());
+ } catch (ConstructableRegistryException e) {
+ logger.error(STARTUP.getMarker(), "Failed to register PlatformTestingToolState", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void registerPlatformClasses(ConstructableRegistry constructableRegistry) {
+ logger.info(STARTUP.getMarker(), "Registering PlatformState classes with ConstructableRegistry");
+ final var schema = new V0540PlatformStateSchema();
+ final StateDefinition def = schema.statesToCreate().iterator().next();
+ final var md = new StateMetadata<>(PlatformStateService.NAME, schema, def);
+ registerWithSystem(md, constructableRegistry);
+ }
+
/**
* save internal file logs and expected map to file while freezing;
* for restart test we should set `saveExpectedMapAtFreeze` to be true, so that
@@ -836,9 +879,12 @@ public void run() {
@Override
@NonNull
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new PlatformTestingToolState());
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new PlatformTestingToolState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(softwareVersion.getSoftwareVersion()));
+ // logger.info(LOGM_STARTUP, "Initializing platform state...");
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
return state;
}
diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolState.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolState.java
index 0681177a515e..3741efab2648 100644
--- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolState.java
+++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolState.java
@@ -31,13 +31,13 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.protobuf.InvalidProtocolBufferException;
+import com.hedera.hapi.node.base.SemanticVersion;
+import com.swirlds.common.constructable.*;
import com.swirlds.common.crypto.CryptographyHolder;
import com.swirlds.common.crypto.SignatureType;
import com.swirlds.common.crypto.TransactionSignature;
import com.swirlds.common.crypto.VerificationStatus;
-import com.swirlds.common.merkle.MerkleInternal;
import com.swirlds.common.merkle.MerkleNode;
-import com.swirlds.common.merkle.impl.PartialNaryMerkleInternal;
import com.swirlds.common.metrics.RunningAverageMetric;
import com.swirlds.common.platform.NodeId;
import com.swirlds.common.utility.ThresholdLimitingHandler;
@@ -83,12 +83,10 @@
import com.swirlds.merkle.test.fixtures.map.pta.MapKey;
import com.swirlds.platform.ParameterProvider;
import com.swirlds.platform.Utilities;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
-import com.swirlds.platform.system.InitTrigger;
-import com.swirlds.platform.system.Platform;
-import com.swirlds.platform.system.Round;
-import com.swirlds.platform.system.SoftwareVersion;
-import com.swirlds.platform.system.SwirldState;
+import com.swirlds.platform.system.*;
import com.swirlds.platform.system.address.AddressBook;
import com.swirlds.platform.system.events.ConsensusEvent;
import com.swirlds.platform.system.events.Event;
@@ -116,6 +114,7 @@
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
@@ -126,9 +125,10 @@
* writes them to the screen, and also saves them to disk in a comma separated value (.csv) file. Each transaction
* consists of an optional sequence number and random bytes.
*/
-public class PlatformTestingToolState extends PartialNaryMerkleInternal implements MerkleInternal, SwirldState {
+@ConstructableIgnored
+public class PlatformTestingToolState extends MerkleStateRoot {
- private static final long CLASS_ID = 0xc0900cfa7a24db76L;
+ static final long CLASS_ID = 0xc0900cfa7a24db76L;
private static final Logger logger = LogManager.getLogger(PlatformTestingToolState.class);
private static final Marker LOGM_DEMO_INFO = MarkerManager.getMarker("DEMO_INFO");
private static final Marker LOGM_EXCEPTION = MarkerManager.getMarker("EXCEPTION");
@@ -243,8 +243,16 @@ public class PlatformTestingToolState extends PartialNaryMerkleInternal implemen
private long transactionsIgnoredByExpectedMap = 0;
- public PlatformTestingToolState() {
- super(ChildIndices.CHILD_COUNT);
+ public PlatformTestingToolState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory) {
+ super(lifecycles, versionFactory);
+
+ // logger.info(
+ // LOGM_DEMO_INFO,
+ // "PlatformTestingToolState., immutable: {}, StackTrace: {}",
+ // isImmutable(),
+ // StackTrace.getStackTrace());
expectedFCMFamily = new ExpectedFCMFamilyImpl();
@@ -254,36 +262,43 @@ public PlatformTestingToolState() {
protected PlatformTestingToolState(final PlatformTestingToolState sourceState) {
super(sourceState);
+ // logger.info(
+ // LOGM_DEMO_INFO,
+ // "PlatformTestingToolState.(COPY), immutable: {}, StackTrace: {}",
+ // isImmutable(),
+ // StackTrace.getStackTrace());
+
this.initialized.set(sourceState.initialized.get());
this.platform = sourceState.platform;
- if (sourceState.getConfig() != null) {
- setConfig(sourceState.getConfig().copy());
- }
-
- if (sourceState.getNextSeqCons() != null) {
- setNextSeqCons(new NextSeqConsList(sourceState.getNextSeqCons()));
- }
-
- if (sourceState.getFcmFamily() != null) {
- setFcmFamily(sourceState.getFcmFamily().copy());
- } else {
- setFcmFamily(new FCMFamily(true));
- }
-
- if (sourceState.getVirtualMap() != null) {
- setVirtualMap(sourceState.getVirtualMap().copy());
- }
-
- if (sourceState.getVirtualMapForSmartContracts() != null) {
- setVirtualMapForSmartContracts(
- sourceState.getVirtualMapForSmartContracts().copy());
- }
-
- if (sourceState.getVirtualMapForSmartContractsByteCode() != null) {
- setVirtualMapForSmartContractsByteCode(
- sourceState.getVirtualMapForSmartContractsByteCode().copy());
- }
+ // commented because copying happens in super
+ // if (sourceState.getConfig() != null) {
+ // setConfig(sourceState.getConfig().copy());
+ // }
+ //
+ // if (sourceState.getNextSeqCons() != null) {
+ // setNextSeqCons(new NextSeqConsList(sourceState.getNextSeqCons()));
+ // }
+ //
+ // if (sourceState.getFcmFamily() != null) {
+ // setFcmFamily(sourceState.getFcmFamily().copy());
+ // } else {
+ // setFcmFamily(new FCMFamily(true));
+ // }
+ //
+ // if (sourceState.getVirtualMap() != null) {
+ // setVirtualMap(sourceState.getVirtualMap().copy());
+ // }
+ //
+ // if (sourceState.getVirtualMapForSmartContracts() != null) {
+ // setVirtualMapForSmartContracts(
+ // sourceState.getVirtualMapForSmartContracts().copy());
+ // }
+ //
+ // if (sourceState.getVirtualMapForSmartContractsByteCode() != null) {
+ // setVirtualMapForSmartContractsByteCode(
+ // sourceState.getVirtualMapForSmartContractsByteCode().copy());
+ // }
this.lastFileTranFinishTimeStamp = sourceState.lastFileTranFinishTimeStamp;
this.lastTranTimeStamp = sourceState.lastTranTimeStamp;
@@ -315,21 +330,21 @@ protected PlatformTestingToolState(final PlatformTestingToolState sourceState) {
}
}
- if (sourceState.getIssLeaf() != null) {
- setIssLeaf(sourceState.getIssLeaf().copy());
- }
+ // if (sourceState.getIssLeaf() != null) {
+ // setIssLeaf(sourceState.getIssLeaf().copy());
+ // }
- if (sourceState.getNftLedger() != null) {
- setNftLedger(sourceState.getNftLedger().copy());
- }
+ // if (sourceState.getNftLedger() != null) {
+ // setNftLedger(sourceState.getNftLedger().copy());
+ // }
// set the current value of QuorumResult from source state
- if (sourceState.getQuorumResult() != null) {
- setQuorumResult(sourceState.getQuorumResult().copy());
- }
- if (controlQuorum != null) {
- controlQuorum.setQuorumResult(getQuorumResult().copy());
- }
+ // if (sourceState.getQuorumResult() != null) {
+ // setQuorumResult(sourceState.getQuorumResult().copy());
+ // }
+ // if (controlQuorum != null) {
+ // controlQuorum.setQuorumResult(getQuorumResult().copy());
+ // }
setImmutable(false);
sourceState.setImmutable(true);
@@ -409,14 +424,6 @@ private static void getCurrentTransactionStat() {
static AtomicLong totalTransactionSignatureCount = new AtomicLong(0);
static AtomicLong expectedInvalidSignatureCount = new AtomicLong(0);
- /**
- * {@inheritDoc}
- */
- @Override
- public int getNumberOfChildren() {
- return ChildIndices.CHILD_COUNT;
- }
-
/**
* {@inheritDoc}
*/
@@ -438,10 +445,18 @@ public int getMaximumChildCount() {
*/
@Override
public boolean childHasExpectedType(final int index, final long childClassId) {
+ // logger.info(
+ // DEMO_INFO.getMarker(),
+ // "Checking if childHasExpectedType for index: {}, childClassId: {}, StackTrace: {}",
+ // index,
+ // childClassId,
+ // StackTrace.getStackTrace());
+
switch (index) {
case ChildIndices.UNUSED:
// We used to use this for an address book, but now we don't use this index.
// Ignore whatever is found at this index.
+ // platform should be here, so check for singleton if all will be ok
return true;
case ChildIndices.CONFIG:
return childClassId == PayloadCfgSimple.CLASS_ID;
@@ -650,7 +665,14 @@ public synchronized ExpectedFCMFamily getStateExpectedMap() {
*/
@Override
public synchronized PlatformTestingToolState copy() {
+ // logger.info(
+ // LOGM_DEMO_INFO,
+ // "PlatformTestingToolState.copy() immutable: {}, StackTrace: {}",
+ // isImmutable(),
+ // StackTrace.getStackTrace());
+
throwIfImmutable();
+ // setImmutable(true);
roundCounter++;
if (transactionsIgnoredByExpectedMap > 0) {
@@ -1305,6 +1327,7 @@ public void init(
@NonNull final Platform platform,
@NonNull final InitTrigger trigger,
@Nullable final SoftwareVersion previousSoftwareVersion) {
+ // super.init(platform, trigger, previousSoftwareVersion);
if (trigger == InitTrigger.RESTART) {
rebuildExpectedMapFromState(Instant.EPOCH, true);
@@ -1646,7 +1669,7 @@ private static class ClassVersion {
}
private static class ChildIndices {
- public static final int UNUSED = 0;
+ public static final int UNUSED = 0; // should be platform and singleton
public static final int CONFIG = 1;
/**
* last sequence by each member for consensus events
diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/TransactionCounter.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/TransactionCounter.java
index caa21f720524..6e6cc87b9e37 100644
--- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/TransactionCounter.java
+++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/TransactionCounter.java
@@ -31,6 +31,8 @@
*/
public class TransactionCounter implements Cloneable, FastCopyable, SelfSerializable {
+ // private static final Marker LOGM_DEMO_INFO = MarkerManager.getMarker("DEMO_INFO");
+
/**
* The version history of this class.
* Versions that have been released must NEVER be given a different value.
@@ -102,6 +104,12 @@ public TransactionCounter(int nodeId) {
public TransactionCounter() {}
private TransactionCounter(final TransactionCounter sourceTransactionCounter) {
+ // logger.info(
+ // LOGM_DEMO_INFO,
+ // "TransactionCounter.(COPY), immutable: {}, StackTrace: {}",
+ // isImmutable(),
+ // StackTrace.getStackTrace());
+
this.fcmCreateAmount = sourceTransactionCounter.fcmCreateAmount;
this.fcmUpdateAmount = sourceTransactionCounter.fcmUpdateAmount;
this.fcmDeleteAmount = sourceTransactionCounter.fcmDeleteAmount;
@@ -129,7 +137,12 @@ private TransactionCounter(final TransactionCounter sourceTransactionCounter) {
@Override
public TransactionCounter copy() {
- throwIfImmutable();
+ // logger.info(
+ // LOGM_DEMO_INFO,
+ // "TransactionCounter.copy(), immutable: {}, StackTrace: {}",
+ // isImmutable(),
+ // StackTrace.getStackTrace());
+ // throwIfImmutable();
return new TransactionCounter(this);
}
diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/module-info.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/module-info.java
index d0009266a88a..818a3bcb6ce0 100644
--- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/module-info.java
@@ -23,6 +23,8 @@
exports com.swirlds.demo.virtualmerkle.config to
com.fasterxml.jackson.databind;
+ // requires com.swirlds.state.impl;
+ requires com.hedera.node.hapi;
requires com.swirlds.base;
requires com.swirlds.common.test.fixtures;
requires com.swirlds.common;
@@ -35,6 +37,8 @@
requires com.swirlds.merkledb;
requires com.swirlds.metrics.api;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
+ requires com.swirlds.state.impl;
requires com.swirlds.virtualmap;
requires com.fasterxml.jackson.annotation;
requires com.fasterxml.jackson.core;
diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/timingSensitive/java/com/swirlds/demo/platform/PttTransactionPoolTest.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/timingSensitive/java/com/swirlds/demo/platform/PttTransactionPoolTest.java
index 1ff76d7aeb62..5f0fc9b30014 100644
--- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/timingSensitive/java/com/swirlds/demo/platform/PttTransactionPoolTest.java
+++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/timingSensitive/java/com/swirlds/demo/platform/PttTransactionPoolTest.java
@@ -43,7 +43,9 @@
import com.swirlds.merkle.test.fixtures.map.lifecycle.LifecycleStatus;
import com.swirlds.merkle.test.fixtures.map.lifecycle.TransactionState;
import com.swirlds.merkle.test.fixtures.map.pta.MapKey;
+import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import java.io.IOException;
import java.time.Instant;
import java.util.Random;
@@ -180,7 +182,8 @@ public void fcqDeleteTest() {
.setOriginNode(otherID)
.build();
try {
- final PlatformTestingToolState state = new PlatformTestingToolState();
+ final PlatformTestingToolState state = new PlatformTestingToolState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(1));
state.setFcmFamily(fCMFamily);
handler.performOperation(
trans,
@@ -237,7 +240,8 @@ public void fcqDeleteNodeTest() {
.setOriginNode(otherID)
.build();
try {
- final PlatformTestingToolState state = new PlatformTestingToolState();
+ final PlatformTestingToolState state = new PlatformTestingToolState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(1));
state.setFcmFamily(fCMFamily);
handler.performOperation(
trans,
diff --git a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolMain.java b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolMain.java
index a6db42b89082..325a995ee4f8 100644
--- a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolMain.java
+++ b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolMain.java
@@ -42,11 +42,11 @@
import com.swirlds.metrics.api.Metrics;
import com.swirlds.platform.Browser;
import com.swirlds.platform.ParameterProvider;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import edu.umd.cs.findbugs.annotations.NonNull;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -272,9 +272,12 @@ private synchronized void generateTransactions() {
@Override
@NonNull
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new StatsSigningTestingToolState(() -> sttTransactionPool));
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new StatsSigningTestingToolState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(softwareVersion.getSoftwareVersion()),
+ () -> sttTransactionPool);
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
return state;
}
diff --git a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolState.java b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolState.java
index 22c71f3f071d..cd78c30a16cf 100644
--- a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolState.java
+++ b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolState.java
@@ -30,26 +30,26 @@
import static com.swirlds.logging.legacy.LogMarker.EXCEPTION;
import static com.swirlds.logging.legacy.LogMarker.TESTING_EXCEPTIONS_ACCEPTABLE_RECONNECT;
+import com.hedera.hapi.node.base.SemanticVersion;
+import com.swirlds.common.constructable.ConstructableIgnored;
import com.swirlds.common.crypto.CryptographyHolder;
import com.swirlds.common.crypto.TransactionSignature;
import com.swirlds.common.crypto.VerificationStatus;
-import com.swirlds.common.io.streams.SerializableDataInputStream;
-import com.swirlds.common.io.streams.SerializableDataOutputStream;
-import com.swirlds.common.merkle.MerkleLeaf;
-import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
import com.swirlds.platform.system.Round;
-import com.swirlds.platform.system.SwirldState;
+import com.swirlds.platform.system.SoftwareVersion;
import com.swirlds.platform.system.events.Event;
import com.swirlds.platform.system.transaction.ConsensusTransaction;
import com.swirlds.platform.system.transaction.Transaction;
import edu.umd.cs.findbugs.annotations.NonNull;
-import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import java.util.function.Function;
import java.util.function.Supplier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -61,7 +61,8 @@
* is 100 random bytes. So StatsSigningDemoState.handleTransaction doesn't actually do anything, other than the
* optional sequence number check.
*/
-public class StatsSigningTestingToolState extends PartialMerkleLeaf implements SwirldState, MerkleLeaf {
+@ConstructableIgnored
+public class StatsSigningTestingToolState extends MerkleStateRoot {
private static final long CLASS_ID = 0x79900efa3127b6eL;
/**
@@ -80,11 +81,11 @@ public class StatsSigningTestingToolState extends PartialMerkleLeaf implements S
/** the number of microseconds to wait before returning from the handle method */
private static final int HANDLE_MICROS = 100;
- public StatsSigningTestingToolState() {
- this(() -> null);
- }
-
- public StatsSigningTestingToolState(@NonNull final Supplier transactionPoolSupplier) {
+ public StatsSigningTestingToolState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory,
+ @NonNull final Supplier transactionPoolSupplier) {
+ super(lifecycles, versionFactory);
this.transactionPoolSupplier = Objects.requireNonNull(transactionPoolSupplier);
}
@@ -101,6 +102,7 @@ private StatsSigningTestingToolState(@NonNull final StatsSigningTestingToolState
@Override
public synchronized StatsSigningTestingToolState copy() {
throwIfImmutable();
+ setImmutable(true);
return new StatsSigningTestingToolState(this);
}
@@ -195,31 +197,6 @@ private boolean validateSignature(final TransactionSignature signature, final Tr
return false;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void serialize(final SerializableDataOutputStream out) throws IOException {
- if (getVersion() >= ClassVersion.KEEP_STATE) {
- out.writeLong(runningSum);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void deserialize(final SerializableDataInputStream in, final int version) throws IOException {
- if (version < ClassVersion.KEEP_STATE) {
- // In this version we serialized an address book
- in.readSerializable();
- }
-
- if (getVersion() >= ClassVersion.KEEP_STATE) {
- runningSum = in.readLong();
- }
- }
-
/**
* {@inheritDoc}
*/
diff --git a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/module-info.java b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/module-info.java
index 509f9f29ca18..0cd6b866b724 100644
--- a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/module-info.java
@@ -1,9 +1,11 @@
module com.swirlds.demo.stats.signing {
+ requires com.hedera.node.hapi;
requires com.swirlds.base;
requires com.swirlds.common;
requires com.swirlds.logging;
requires com.swirlds.metrics.api;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
requires com.hedera.pbj.runtime;
requires lazysodium.java;
requires org.apache.logging.log4j;
diff --git a/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolMain.java b/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolMain.java
index 817aa74f438e..dd91221963c4 100644
--- a/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolMain.java
+++ b/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolMain.java
@@ -39,11 +39,11 @@
import com.swirlds.common.threading.framework.config.ThreadConfiguration;
import com.swirlds.metrics.api.Metrics;
import com.swirlds.platform.Browser;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
+import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.List;
@@ -231,9 +231,11 @@ private synchronized void generateTransactions() {
}
@Override
- public MerkleRoot newMerkleStateRoot() {
- final State state = new State();
- state.setSwirldState(new StressTestingToolState());
+ public MerkleStateRoot newMerkleStateRoot() {
+ final MerkleStateRoot state = new StressTestingToolState(
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES,
+ version -> new BasicSoftwareVersion(SOFTWARE_VERSION.getSoftwareVersion()));
+ NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
return state;
}
diff --git a/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolState.java b/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolState.java
index c4885e40e090..92bda480b8ed 100644
--- a/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolState.java
+++ b/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/com/swirlds/demo/stress/StressTestingToolState.java
@@ -26,29 +26,29 @@
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
-import com.swirlds.common.io.streams.SerializableDataInputStream;
-import com.swirlds.common.io.streams.SerializableDataOutputStream;
-import com.swirlds.common.merkle.MerkleLeaf;
-import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
+import com.hedera.hapi.node.base.SemanticVersion;
+import com.swirlds.common.constructable.ConstructableIgnored;
import com.swirlds.common.utility.ByteUtils;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.PlatformStateModifier;
import com.swirlds.platform.system.InitTrigger;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.Round;
import com.swirlds.platform.system.SoftwareVersion;
-import com.swirlds.platform.system.SwirldState;
import com.swirlds.platform.system.events.Event;
import com.swirlds.platform.system.transaction.ConsensusTransaction;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-import java.io.IOException;
import java.time.Duration;
+import java.util.function.Function;
/**
* This testing tool simulates configurable processing times for both preHandling and handling for stress testing
* purposes.
*/
-public class StressTestingToolState extends PartialMerkleLeaf implements SwirldState, MerkleLeaf {
+@ConstructableIgnored
+public class StressTestingToolState extends MerkleStateRoot {
private static final long CLASS_ID = 0x79900efa3127b6eL;
/** A running sum of transaction contents */
@@ -57,8 +57,11 @@ public class StressTestingToolState extends PartialMerkleLeaf implements SwirldS
/** supplies the app config */
public StressTestingToolConfig config;
- @SuppressWarnings("unused")
- public StressTestingToolState() {}
+ public StressTestingToolState(
+ @NonNull final MerkleStateLifecycles lifecycles,
+ @NonNull final Function versionFactory) {
+ super(lifecycles, versionFactory);
+ }
private StressTestingToolState(@NonNull final StressTestingToolState sourceState) {
super(sourceState);
@@ -74,6 +77,7 @@ private StressTestingToolState(@NonNull final StressTestingToolState sourceState
@Override
public synchronized StressTestingToolState copy() {
throwIfImmutable();
+ setImmutable(true);
return new StressTestingToolState(this);
}
@@ -84,6 +88,8 @@ public void init(
@NonNull final Platform platform,
@NonNull final InitTrigger trigger,
@Nullable final SoftwareVersion previousSoftwareVersion) {
+ super.init(platform, trigger, previousSoftwareVersion);
+
this.config = platform.getContext().getConfiguration().getConfigData(StressTestingToolConfig.class);
}
@@ -124,22 +130,6 @@ private void busyWait(@NonNull final Duration duration) {
}
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void serialize(@NonNull final SerializableDataOutputStream out) throws IOException {
- out.writeLong(runningSum);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void deserialize(@NonNull final SerializableDataInputStream in, final int version) throws IOException {
- runningSum = in.readLong();
- }
-
/**
* {@inheritDoc}
*/
diff --git a/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/module-info.java b/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/module-info.java
index 056479da84b5..237005494096 100644
--- a/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/module-info.java
+++ b/platform-sdk/platform-apps/tests/StressTestingTool/src/main/java/module-info.java
@@ -1,10 +1,12 @@
module com.swirlds.demo.stress {
+ requires com.hedera.node.hapi;
requires com.swirlds.base;
requires com.swirlds.common;
requires com.swirlds.config.api;
requires com.swirlds.logging;
requires com.swirlds.metrics.api;
requires com.swirlds.platform.core;
+ requires com.swirlds.state.api;
requires com.hedera.pbj.runtime;
requires org.apache.logging.log4j;
requires static com.github.spotbugs.annotations;
diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/MerkleStateRoot.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/MerkleStateRoot.java
index a4ffddbad224..b1f63a2d318a 100644
--- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/MerkleStateRoot.java
+++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/MerkleStateRoot.java
@@ -16,7 +16,7 @@
package com.swirlds.platform.state;
-import static com.swirlds.logging.legacy.LogMarker.EXCEPTION;
+import static com.swirlds.logging.legacy.LogMarker.*;
import static com.swirlds.platform.state.MerkleStateUtils.createInfoString;
import static com.swirlds.platform.state.service.schemas.V0540PlatformStateSchema.PLATFORM_STATE_KEY;
import static com.swirlds.platform.system.InitTrigger.EVENT_STREAM_RECOVERY;
@@ -432,6 +432,8 @@ public void putServiceStateIfAbsent(
@NonNull final Supplier nodeSupplier,
@NonNull final Consumer nodeInitializer) {
+ logger.info(STARTUP.getMarker(), "Putting states... ", md.serviceName());
+
// Validate the inputs
throwIfImmutable();
requireNonNull(md);
@@ -449,6 +451,8 @@ public void putServiceStateIfAbsent(
readableStatesMap.put(serviceName, new MerkleReadableStates(stateMetadata));
writableStatesMap.put(serviceName, new MerkleWritableStates(serviceName, stateMetadata));
+ logger.info(STARTUP.getMarker(), "Put states! Service name: {} ", md.serviceName());
+
// Look for a node, and if we don't find it, then insert the one we were given
// If there is not a node there, then set it. I don't want to overwrite the existing node,
// because it may have been loaded from state on disk, and the node provided here in this
@@ -478,8 +482,21 @@ public void putServiceStateIfAbsent(
"A label must be computed based on the same " + "service name and state key in the metadata!");
}
+ logger.info(
+ STARTUP.getMarker(),
+ "Setting child.. Service name: {} / Number of children: {} / node: {}",
+ md.serviceName(),
+ getNumberOfChildren(),
+ node);
setChild(getNumberOfChildren(), node);
} else {
+ logger.info(
+ STARTUP.getMarker(),
+ "Getting child.. Service name: {} / Number of children: {} / node: {}",
+ md.serviceName(),
+ getNumberOfChildren(),
+ nodeIndex);
+
node = getChild(nodeIndex);
}
nodeInitializer.accept(node);
diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/State.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/State.java
deleted file mode 100644
index b161872e0d93..000000000000
--- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/State.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2016-2024 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.
- */
-
-package com.swirlds.platform.state;
-
-import static com.swirlds.platform.state.MerkleStateUtils.createInfoString;
-
-import com.swirlds.base.utility.ToStringBuilder;
-import com.swirlds.common.merkle.MerkleNode;
-import com.swirlds.common.merkle.impl.PartialNaryMerkleInternal;
-import com.swirlds.common.merkle.route.MerkleRouteFactory;
-import com.swirlds.common.utility.RuntimeObjectRecord;
-import com.swirlds.common.utility.RuntimeObjectRegistry;
-import com.swirlds.platform.system.SwirldState;
-import edu.umd.cs.findbugs.annotations.NonNull;
-import java.nio.file.Path;
-import java.util.Objects;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-/**
- * The root of the merkle tree holding the state of the Swirlds ledger. Contains two children: the state used by the
- * application and the state used by the platform.
- *
- * @deprecated This class is deprecated for usage as production code.
- * It should be only used for testing purposes and will be moved to testFixtures in 0.54.
- */
-@Deprecated(forRemoval = true, since = "0.53.0")
-public class State extends PartialNaryMerkleInternal implements MerkleRoot {
-
- private static final Logger logger = LogManager.getLogger(State.class);
-
- private static final long CLASS_ID = 0x2971b4ba7dd84402L;
-
- public static class ClassVersion {
- public static final int ORIGINAL = 1;
- public static final int ADD_MIN_GEN = 2;
- public static final int EVENT_REFACTOR = 3;
- public static final int MIGRATE_TO_SERIALIZABLE = 4;
- public static final int ADD_DUAL_STATE = 5;
- public static final int REMOVE_DUAL_STATE = 6;
- public static final int MIGRATE_PLATFORM_STATE = 7;
- }
-
- private static class ChildIndices {
- /**
- * The state written and used by the application. It is the state resulting from all transactions in consensus
- * order from all events with received rounds up through the round this State represents.
- */
- public static final int SWIRLD_STATE = 0;
- /**
- * The state written and used by the platform.
- */
- public static final int PLATFORM_STATE = 1;
- }
-
- /**
- * Used to track the lifespan of this state.
- */
- private final RuntimeObjectRecord registryRecord;
-
- public State() {
- registryRecord = RuntimeObjectRegistry.createRecord(getClass());
- updatePlatformState(new PlatformState());
- }
-
- private State(final State that) {
- super(that);
-
- registryRecord = RuntimeObjectRegistry.createRecord(getClass());
-
- if (that.getSwirldState() != null) {
- this.setSwirldState(that.getSwirldState().copy());
- }
- if (that.getWritablePlatformState() != null) {
- this.updatePlatformState(that.getWritablePlatformState().copy());
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public MerkleNode migrate(final int version) {
- if (version < ClassVersion.REMOVE_DUAL_STATE) {
- throw new UnsupportedOperationException("State migration from version " + version + " is not supported."
- + " The minimum supported version is " + getMinimumSupportedVersion());
- }
-
- if (version < ClassVersion.MIGRATE_PLATFORM_STATE
- && getSwirldState() instanceof MerkleStateRoot merkleStateRoot) {
- PlatformState platformState = getWritablePlatformState().copy();
- setChild(ChildIndices.PLATFORM_STATE, null);
- merkleStateRoot.updatePlatformState(platformState);
- merkleStateRoot.setRoute(MerkleRouteFactory.getEmptyRoute());
- return merkleStateRoot.copy();
- }
-
- return this;
- }
- /**
- * {@inheritDoc}
- */
- @Override
- public int getMinimumSupportedVersion() {
- return ClassVersion.REMOVE_DUAL_STATE;
- }
-
- /**
- * Get the application state.
- *
- * @return the application state
- */
- @Override
- @NonNull
- public SwirldState getSwirldState() {
- return getChild(ChildIndices.SWIRLD_STATE);
- }
-
- /**
- * Set the application state.
- *
- * @param state the application state
- */
- public void setSwirldState(final SwirldState state) {
- setChild(ChildIndices.SWIRLD_STATE, state);
- }
-
- /**
- * Immutable platform state is not supported by this class.
- */
- @NonNull
- @Override
- public PlatformStateAccessor getReadablePlatformState() {
- return getChild(ChildIndices.PLATFORM_STATE);
- }
-
- /**
- * Get the platform state.
- * @return the platform state
- */
- @NonNull
- @Override
- public PlatformState getWritablePlatformState() {
- return getChild(ChildIndices.PLATFORM_STATE);
- }
-
- /**
- * Updates the platform state.
- *
- * @param modifier the platform state
- */
- @Override
- public void updatePlatformState(@NonNull final PlatformStateModifier modifier) {
- if (modifier instanceof PlatformState platformState) {
- setChild(ChildIndices.PLATFORM_STATE, platformState);
- } else {
- throw new UnsupportedOperationException("%s implementation of %s is not supported"
- .formatted(modifier.getClass().getSimpleName(), PlatformStateModifier.class.getSimpleName()));
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public long getClassId() {
- return CLASS_ID;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getVersion() {
- return ClassVersion.MIGRATE_PLATFORM_STATE;
- }
-
- /**
- * {@inheritDoc}
- */
- @NonNull
- @Override
- public MerkleRoot copy() {
- throwIfImmutable();
- throwIfDestroyed();
- setImmutable(true);
- return new State(this);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void destroyNode() {
- registryRecord.release();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(final Object other) {
- if (this == other) {
- return true;
- }
- if (other == null || getClass() != other.getClass()) {
- return false;
- }
- final MerkleRoot state = (MerkleRoot) other;
- return Objects.equals(getReadablePlatformState(), state.getReadablePlatformState())
- && Objects.equals(getSwirldState(), state.getSwirldState());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return Objects.hash(getReadablePlatformState(), getSwirldState());
- }
-
- /**
- * Generate a string that describes this state.
- *
- * @param hashDepth the depth of the tree to visit and print
- */
- @NonNull
- @Override
- public String getInfoString(final int hashDepth) {
- final PlatformStateAccessor platformState = getReadablePlatformState();
- return createInfoString(hashDepth, platformState, getHash(), this);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void createSnapshot(@NonNull final Path targetPath) {
- throwIfMutable();
- throwIfDestroyed();
- MerkleTreeSnapshotWriter.createSnapshot(this, targetPath);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- return new ToStringBuilder(this)
- .append("platformState", getReadablePlatformState())
- .append("swirldState", getSwirldState())
- .toString();
- }
-}
diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/util/NoOpMerkleStateLifecycles.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/util/NoOpMerkleStateLifecycles.java
new file mode 100644
index 000000000000..5de7b6e9373f
--- /dev/null
+++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/util/NoOpMerkleStateLifecycles.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.swirlds.platform.util;
+
+import com.hedera.hapi.block.stream.output.StateChanges;
+import com.hedera.hapi.node.base.SemanticVersion;
+import com.swirlds.common.context.PlatformContext;
+import com.swirlds.config.api.Configuration;
+import com.swirlds.platform.state.MerkleStateLifecycles;
+import com.swirlds.platform.state.MerkleStateRoot;
+import com.swirlds.platform.state.service.PlatformStateService;
+import com.swirlds.platform.state.service.schemas.V0540PlatformStateSchema;
+import com.swirlds.platform.system.*;
+import com.swirlds.platform.system.address.AddressBook;
+import com.swirlds.platform.system.events.Event;
+import com.swirlds.state.State;
+import com.swirlds.state.lifecycle.MigrationContext;
+import com.swirlds.state.lifecycle.StateDefinition;
+import com.swirlds.state.lifecycle.info.NetworkInfo;
+import com.swirlds.state.merkle.StateMetadata;
+import com.swirlds.state.merkle.singleton.SingletonNode;
+import com.swirlds.state.spi.*;
+import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.MarkerManager;
+
+public enum NoOpMerkleStateLifecycles implements MerkleStateLifecycles {
+ NO_OP_MERKLE_STATE_LIFECYCLES;
+
+ private static final Logger logger = LogManager.getLogger(NoOpMerkleStateLifecycles.class);
+
+ public List initPlatformState(@NonNull final State state) {
+ logger.info(MarkerManager.getMarker("DEMO_INFO"), "Init Platform State...");
+
+ if (!(state instanceof MerkleStateRoot merkleStateRoot)) {
+ throw new IllegalArgumentException("Can only be used with MerkleStateRoot instances");
+ }
+ final var schema = new V0540PlatformStateSchema();
+ schema.statesToCreate().stream()
+ .sorted(Comparator.comparing(StateDefinition::stateKey))
+ .forEach(def -> {
+ final var md = new StateMetadata<>(PlatformStateService.NAME, schema, def);
+ if (def.singleton()) {
+ merkleStateRoot.putServiceStateIfAbsent(
+ md,
+ () -> new SingletonNode<>(
+ md.serviceName(),
+ md.stateDefinition().stateKey(),
+ md.singletonClassId(),
+ md.stateDefinition().valueCodec(),
+ null));
+ } else {
+ throw new IllegalStateException("PlatformStateService only expected to use singleton states");
+ }
+ });
+
+ final var writableStates = state.getWritableStates(PlatformStateService.NAME);
+
+ logger.info(MarkerManager.getMarker("DEMO_INFO"), "Writable states: {}", writableStates.stateKeys());
+
+ final var migrationContext = new MigrationContext() {
+ @NonNull
+ @Override
+ public ReadableStates previousStates() {
+ return null;
+ }
+
+ @NonNull
+ @Override
+ public WritableStates newStates() {
+ return writableStates;
+ }
+
+ @NonNull
+ @Override
+ public Configuration configuration() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public NetworkInfo genesisNetworkInfo() {
+ return null;
+ }
+
+ @Override
+ public long newEntityNum() {
+ return 0;
+ }
+
+ @Override
+ public void copyAndReleaseOnDiskState(String stateKey) {
+ // no-op
+ }
+
+ @Nullable
+ @Override
+ public SemanticVersion previousVersion() {
+ return null;
+ }
+
+ @Override
+ public Map sharedValues() {
+ return Map.of();
+ }
+ };
+
+ logger.info(
+ MarkerManager.getMarker("DEMO_INFO"),
+ "(MigrationContext) Writable states: {}",
+ migrationContext.newStates().stateKeys());
+
+ schema.migrate(migrationContext);
+ ((CommittableWritableStates) writableStates).commit();
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void onPreHandle(@NonNull Event event, @NonNull State state) {
+ // no-op
+ }
+
+ @Override
+ public void onHandleConsensusRound(@NonNull Round round, @NonNull State state) {
+ // no-op
+ }
+
+ @Override
+ public void onSealConsensusRound(@NonNull Round round, @NonNull State state) {
+ // Touch this round
+ round.getRoundNum();
+ }
+
+ @Override
+ public void onStateInitialized(
+ @NonNull State state,
+ @NonNull Platform platform,
+ @NonNull InitTrigger trigger,
+ @Nullable SoftwareVersion previousVersion) {
+ // no-op
+ }
+
+ @Override
+ public void onUpdateWeight(
+ @NonNull MerkleStateRoot state, @NonNull AddressBook configAddressBook, @NonNull PlatformContext context) {
+ // no-op
+ }
+
+ @Override
+ public void onNewRecoveredState(@NonNull MerkleStateRoot recoveredState) {
+ // no-op
+ }
+}
diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/StateRegistryTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/StateRegistryTests.java
index 84be53777929..189d8eff00b9 100644
--- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/StateRegistryTests.java
+++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/StateRegistryTests.java
@@ -81,7 +81,10 @@ void activeStateCountTest() throws IOException {
// Restore the registry to its original condition at boot time
RuntimeObjectRegistry.reset();
- assertEquals(0, RuntimeObjectRegistry.getActiveObjectsCount(State.class), "no states have been created yet");
+ assertEquals(
+ 0,
+ RuntimeObjectRegistry.getActiveObjectsCount(MerkleStateRoot.class),
+ "no states have been created yet");
final List states = new LinkedList<>();
// Create a bunch of states
diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/Turtle.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/Turtle.java
index fd00324d1209..04fdf341fdbc 100644
--- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/Turtle.java
+++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/Turtle.java
@@ -16,11 +16,16 @@
package com.swirlds.platform.turtle.runner;
+import static com.swirlds.platform.test.fixtures.state.FakeMerkleStateLifecycles.FAKE_MERKLE_STATE_LIFECYCLES;
+
import com.swirlds.base.test.fixtures.time.FakeTime;
+import com.swirlds.common.constructable.ClassConstructorPair;
import com.swirlds.common.constructable.ConstructableRegistry;
import com.swirlds.common.constructable.ConstructableRegistryException;
import com.swirlds.common.platform.NodeId;
import com.swirlds.common.test.fixtures.Randotron;
+import com.swirlds.platform.state.MerkleStateRoot;
+import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.address.AddressBook;
import com.swirlds.platform.test.fixtures.addressbook.RandomAddressBookBuilder;
import com.swirlds.platform.test.fixtures.turtle.gossip.SimulatedNetwork;
@@ -96,7 +101,11 @@ public class Turtle {
timeReportingEnabled = builder.isTimeReportingEnabled();
try {
- ConstructableRegistry.getInstance().registerConstructables("");
+ ConstructableRegistry.getInstance()
+ .registerConstructable(new ClassConstructorPair(
+ MerkleStateRoot.class,
+ () -> new MerkleStateRoot(
+ FAKE_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(1))));
} catch (final ConstructableRegistryException e) {
throw new RuntimeException(e);
}
diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleNode.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleNode.java
index 10c2e6034fd5..d1afab65cf41 100644
--- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleNode.java
+++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleNode.java
@@ -18,6 +18,7 @@
import static com.swirlds.common.threading.manager.AdHocThreadManager.getStaticThreadManager;
import static com.swirlds.platform.builder.internal.StaticPlatformBuilder.getMetricsProvider;
+import static com.swirlds.platform.builder.internal.StaticPlatformBuilder.setupGlobalMetrics;
import static com.swirlds.platform.state.signed.StartupStateUtils.getInitialState;
import com.swirlds.base.time.Time;
@@ -91,6 +92,8 @@ public class TurtleNode {
.withValue(BasicConfig_.JVM_PAUSE_DETECTOR_SLEEP_MS, "0")
.getOrCreateConfig();
+ setupGlobalMetrics(configuration);
+
final PlatformContext platformContext = TestPlatformContextBuilder.create()
.withTime(time)
.withConfiguration(configuration)
@@ -102,11 +105,10 @@ public class TurtleNode {
final Supplier genesisStateSupplier = TurtleTestingToolState::getStateRootNode;
final var version = new BasicSoftwareVersion(1);
- final NodeId selfId = null;
- final var metrics = getMetricsProvider().createPlatformMetrics(selfId);
+ final var metrics = getMetricsProvider().createPlatformMetrics(nodeId);
final var fileSystemManager = FileSystemManager.create(configuration);
final var recycleBin =
- RecycleBin.create(metrics, configuration, getStaticThreadManager(), time, fileSystemManager, selfId);
+ RecycleBin.create(metrics, configuration, getStaticThreadManager(), time, fileSystemManager, nodeId);
final var reservedState = getInitialState(
configuration, recycleBin, version, genesisStateSupplier, "foo", "bar", nodeId, addressBook);
diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java
index 6ab2196681e3..e954300d27a6 100644
--- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java
+++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/turtle/runner/TurtleTestingToolState.java
@@ -16,18 +16,13 @@
package com.swirlds.platform.turtle.runner;
-import com.swirlds.common.io.streams.SerializableDataInputStream;
-import com.swirlds.common.io.streams.SerializableDataOutputStream;
-import com.swirlds.common.merkle.MerkleLeaf;
-import com.swirlds.common.merkle.impl.PartialMerkleLeaf;
+import static com.swirlds.platform.test.fixtures.state.FakeMerkleStateLifecycles.FAKE_MERKLE_STATE_LIFECYCLES;
+
import com.swirlds.common.utility.NonCryptographicHashing;
-import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.PlatformStateModifier;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.*;
+import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Round;
-import com.swirlds.platform.system.SwirldState;
import edu.umd.cs.findbugs.annotations.NonNull;
-import java.io.IOException;
/**
* A simple testing application intended for use with TURTLE.
@@ -37,7 +32,7 @@
* ﹉∏﹉∏﹉ ﹉∏﹉∏﹉
*
*/
-public class TurtleTestingToolState extends PartialMerkleLeaf implements SwirldState, MerkleLeaf {
+public class TurtleTestingToolState extends MerkleStateRoot {
private static final long CLASS_ID = 0xa49b3822a4136ac6L;
@@ -48,18 +43,18 @@ private static final class ClassVersion {
private long state;
- /**
- * Zero arg constructor needed for constructable registry.
- */
- public TurtleTestingToolState() {}
+ public TurtleTestingToolState() {
+ super(FAKE_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(1));
+ }
/**
* Copy constructor.
*
- * @param that the object to copy
+ * @param from the object to copy
*/
- private TurtleTestingToolState(@NonNull final TurtleTestingToolState that) {
- this.state = that.state;
+ private TurtleTestingToolState(@NonNull final TurtleTestingToolState from) {
+ super(from);
+ this.state = from.state;
}
/**
@@ -95,25 +90,11 @@ public void handleConsensusRound(@NonNull final Round round, @NonNull final Plat
*/
@Override
public TurtleTestingToolState copy() {
+ throwIfImmutable();
+ setImmutable(true);
return new TurtleTestingToolState(this);
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void serialize(@NonNull final SerializableDataOutputStream out) throws IOException {
- out.writeLong(state);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void deserialize(@NonNull final SerializableDataInputStream in, final int version) throws IOException {
- state = in.readLong();
- }
-
/**
* Creates a merkle node to act as a state tree root.
*
@@ -121,9 +102,8 @@ public void deserialize(@NonNull final SerializableDataInputStream in, final int
*/
@NonNull
public static MerkleRoot getStateRootNode() {
- final TurtleTestingToolState turtleState = new TurtleTestingToolState();
- final State root = new State();
- root.setSwirldState(turtleState);
- return root;
+ final MerkleStateRoot state = new TurtleTestingToolState();
+ FAKE_MERKLE_STATE_LIFECYCLES.initPlatformState(state);
+ return state;
}
}
diff --git a/platform-sdk/swirlds-state-impl/src/main/java/com/swirlds/state/merkle/StateUtils.java b/platform-sdk/swirlds-state-impl/src/main/java/com/swirlds/state/merkle/StateUtils.java
index c27999baa925..fdd816b472ee 100644
--- a/platform-sdk/swirlds-state-impl/src/main/java/com/swirlds/state/merkle/StateUtils.java
+++ b/platform-sdk/swirlds-state-impl/src/main/java/com/swirlds/state/merkle/StateUtils.java
@@ -23,17 +23,35 @@
import com.hedera.pbj.runtime.ParseException;
import com.hedera.pbj.runtime.io.stream.ReadableStreamingData;
import com.hedera.pbj.runtime.io.stream.WritableStreamingData;
+import com.swirlds.common.constructable.ClassConstructorPair;
+import com.swirlds.common.constructable.ConstructableRegistry;
+import com.swirlds.common.constructable.ConstructableRegistryException;
import com.swirlds.common.utility.NonCryptographicHashing;
+import com.swirlds.logging.legacy.LogMarker;
+import com.swirlds.state.merkle.disk.OnDiskKey;
+import com.swirlds.state.merkle.disk.OnDiskKeySerializer;
+import com.swirlds.state.merkle.disk.OnDiskValue;
+import com.swirlds.state.merkle.disk.OnDiskValueSerializer;
+import com.swirlds.state.merkle.memory.InMemoryValue;
+import com.swirlds.state.merkle.memory.InMemoryWritableKVState;
+import com.swirlds.state.merkle.queue.QueueNode;
+import com.swirlds.state.merkle.singleton.SingletonNode;
+import com.swirlds.state.merkle.singleton.StringLeaf;
+import com.swirlds.state.merkle.singleton.ValueLeaf;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
/** Utility class for working with states. */
public final class StateUtils {
+ private static final Logger logger = LogManager.getLogger(StateUtils.class);
+
/** Prevent instantiation */
private StateUtils() {}
@@ -176,7 +194,9 @@ static long hashString(@NonNull final String s) {
// Normalize the string so things are deterministic (different JVMs might be using different
// default internal representation for strings, and we need to normalize that)
final var data = getNormalisedStringBytes(s);
- return hashBytes(data);
+ long l = hashBytes(data);
+ logger.info(LogMarker.STARTUP.getMarker(), "Hashed string {} to {}", s, l);
+ return l;
}
// Will be moved to `NonCryptographicHashing` with
@@ -242,4 +262,82 @@ private static boolean isAsciiLetter(char ch) {
private static boolean isAsciiNumber(char ch) {
return ch >= '0' && ch <= '9';
}
+
+ /**
+ * Registers with the {@link ConstructableRegistry} system a class ID and a class. While this
+ * will only be used for in-memory states, it is safe to register for on-disk ones as well.
+ *
+ * The implementation will take the service name and the state key and compute a hash for it.
+ * It will then convert the hash to a long, and use that as the class ID. It will then register
+ * an {@link InMemoryWritableKVState}'s value merkle type to be deserialized, answering with the
+ * generated class ID.
+ *
+ * @param md The state metadata
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public static void registerWithSystem(
+ @NonNull final StateMetadata md, @NonNull ConstructableRegistry constructableRegistry) {
+ // Register with the system the uniqueId as the "classId" of an InMemoryValue. There can be
+ // multiple id's associated with InMemoryValue. The secret is that the supplier captures the
+ // various delegate writers and parsers, and so can parse/write different types of data
+ // based on the id.
+ try {
+ constructableRegistry.registerConstructable(new ClassConstructorPair(
+ InMemoryValue.class,
+ () -> new InMemoryValue(
+ md.inMemoryValueClassId(),
+ md.stateDefinition().keyCodec(),
+ md.stateDefinition().valueCodec())));
+ constructableRegistry.registerConstructable(new ClassConstructorPair(
+ OnDiskKey.class,
+ () -> new OnDiskKey<>(
+ md.onDiskKeyClassId(), md.stateDefinition().keyCodec())));
+ constructableRegistry.registerConstructable(new ClassConstructorPair(
+ OnDiskKeySerializer.class,
+ () -> new OnDiskKeySerializer<>(
+ md.onDiskKeySerializerClassId(),
+ md.onDiskKeyClassId(),
+ md.stateDefinition().keyCodec())));
+ constructableRegistry.registerConstructable(new ClassConstructorPair(
+ OnDiskValue.class,
+ () -> new OnDiskValue<>(
+ md.onDiskValueClassId(), md.stateDefinition().valueCodec())));
+ constructableRegistry.registerConstructable(new ClassConstructorPair(
+ OnDiskValueSerializer.class,
+ () -> new OnDiskValueSerializer<>(
+ md.onDiskValueSerializerClassId(),
+ md.onDiskValueClassId(),
+ md.stateDefinition().valueCodec())));
+ constructableRegistry.registerConstructable(new ClassConstructorPair(
+ SingletonNode.class,
+ () -> new SingletonNode<>(
+ md.serviceName(),
+ md.stateDefinition().stateKey(),
+ md.singletonClassId(),
+ md.stateDefinition().valueCodec(),
+ null)));
+ constructableRegistry.registerConstructable(new ClassConstructorPair(
+ QueueNode.class,
+ () -> new QueueNode<>(
+ md.serviceName(),
+ md.stateDefinition().stateKey(),
+ md.queueNodeClassId(),
+ md.singletonClassId(),
+ md.stateDefinition().valueCodec())));
+ constructableRegistry.registerConstructable(new ClassConstructorPair(StringLeaf.class, StringLeaf::new));
+ constructableRegistry.registerConstructable(new ClassConstructorPair(
+ ValueLeaf.class,
+ () -> new ValueLeaf<>(
+ md.singletonClassId(), md.stateDefinition().valueCodec())));
+ } catch (ConstructableRegistryException e) {
+ // This is a fatal error.
+ throw new IllegalStateException(
+ "Failed to register with the system '"
+ + md.serviceName()
+ + ":"
+ + md.stateDefinition().stateKey()
+ + "'",
+ e);
+ }
+ }
}
diff --git a/platform-sdk/swirlds-state-impl/src/main/java/com/swirlds/state/merkle/singleton/SingletonNode.java b/platform-sdk/swirlds-state-impl/src/main/java/com/swirlds/state/merkle/singleton/SingletonNode.java
index 76f8ec9816bb..10cb1298f358 100644
--- a/platform-sdk/swirlds-state-impl/src/main/java/com/swirlds/state/merkle/singleton/SingletonNode.java
+++ b/platform-sdk/swirlds-state-impl/src/main/java/com/swirlds/state/merkle/singleton/SingletonNode.java
@@ -37,7 +37,7 @@
*/
@DebugIterationEndpoint
public class SingletonNode extends PartialBinaryMerkleInternal implements Labeled, MerkleInternal {
- static final long CLASS_ID = 0x3832CC837AB77BFL;
+ public static final long CLASS_ID = 0x3832CC837AB77BFL;
public static final int CLASS_VERSION = 1;
/**
diff --git a/platform-sdk/swirlds-state-impl/src/main/java/module-info.java b/platform-sdk/swirlds-state-impl/src/main/java/module-info.java
index a899fb136f79..eb3c88b67d11 100644
--- a/platform-sdk/swirlds-state-impl/src/main/java/module-info.java
+++ b/platform-sdk/swirlds-state-impl/src/main/java/module-info.java
@@ -12,6 +12,7 @@
requires transitive com.swirlds.virtualmap;
requires transitive com.hedera.pbj.runtime;
requires com.swirlds.fcqueue;
+ requires com.swirlds.logging;
requires org.apache.logging.log4j;
requires static transitive com.github.spotbugs.annotations;
}
diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTest.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTest.java
index beb1563b8d32..6ae696dc8ba4 100644
--- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTest.java
+++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTest.java
@@ -30,7 +30,6 @@
import com.swirlds.platform.crypto.CryptoStatic;
import com.swirlds.platform.state.MerkleRoot;
import com.swirlds.platform.state.MerkleStateRoot;
-import com.swirlds.platform.state.State;
import com.swirlds.platform.state.signed.SignedState;
import com.swirlds.platform.system.BasicSoftwareVersion;
import java.util.Random;
@@ -86,14 +85,13 @@ void tryReserveTest() {
private static SignedState randomSignedState() {
Random random = new Random(0);
- State root = new State();
- root.setSwirldState(new MerkleStateRoot(
- FAKE_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(version.major())));
+ MerkleStateRoot merkleStateRoot =
+ new MerkleStateRoot(FAKE_MERKLE_STATE_LIFECYCLES, version -> new BasicSoftwareVersion(version.major()));
boolean shouldSaveToDisk = random.nextBoolean();
SignedState signedState = new SignedState(
TestPlatformContextBuilder.create().build().getConfiguration(),
CryptoStatic::verifySignature,
- root,
+ merkleStateRoot,
"test",
shouldSaveToDisk,
false,
diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTests.java
index d8569b653915..780c02336dd7 100644
--- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTests.java
+++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/StateTests.java
@@ -27,7 +27,7 @@
import com.swirlds.common.test.fixtures.junit.tags.TestComponentTags;
import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder;
import com.swirlds.platform.state.MerkleRoot;
-import com.swirlds.platform.state.State;
+import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.test.fixtures.state.BlockingSwirldState;
import java.io.IOException;
import java.nio.file.Path;
@@ -40,7 +40,7 @@
@DisplayName("State Tests")
class StateTests {
- private static State state;
+ private static MerkleStateRoot merkleStateRoot;
/**
* Temporary directory provided by JUnit
*/
@@ -53,11 +53,10 @@ static void setUp() throws ConstructableRegistryException {
ConstructableRegistry.getInstance().registerConstructables("com.swirlds");
- state = new State();
- state.setSwirldState(new BlockingSwirldState());
+ merkleStateRoot = new BlockingSwirldState();
- state.invalidateHash();
- MerkleCryptoFactory.getInstance().digestTreeSync(state);
+ merkleStateRoot.invalidateHash();
+ MerkleCryptoFactory.getInstance().digestTreeSync(merkleStateRoot);
}
@Test
@@ -67,25 +66,25 @@ static void setUp() throws ConstructableRegistryException {
void stateSerializationTest() throws IOException {
InputOutputStream io = new InputOutputStream();
- io.getOutput().writeMerkleTree(testDirectory, state);
+ io.getOutput().writeMerkleTree(testDirectory, merkleStateRoot);
io.startReading();
final MerkleRoot decodedState = io.getInput().readMerkleTree(testDirectory, Integer.MAX_VALUE);
MerkleCryptoFactory.getInstance().digestTreeSync(decodedState);
- assertEquals(state.getHash(), decodedState.getHash(), "expected trees to be equal");
- assertTrue(areTreesEqual(state, decodedState), "expected trees to be equal");
+ assertEquals(merkleStateRoot.getHash(), decodedState.getHash(), "expected trees to be equal");
+ assertTrue(areTreesEqual(merkleStateRoot, decodedState), "expected trees to be equal");
}
@Test
@Tag(TestComponentTags.PLATFORM)
@DisplayName("State Copy Test")
void stateCopyTest() {
- final MerkleRoot copiedState = state.copy();
+ final MerkleRoot copiedState = merkleStateRoot.copy();
MerkleCryptoFactory.getInstance().digestTreeSync(copiedState);
- assertEquals(state.getHash(), copiedState.getHash(), "expected trees to be equal");
- assertTrue(areTreesEqual(state, copiedState), "expected trees to be equal");
+ assertEquals(merkleStateRoot.getHash(), copiedState.getHash(), "expected trees to be equal");
+ assertTrue(areTreesEqual(merkleStateRoot, copiedState), "expected trees to be equal");
}
}