Skip to content

Commit

Permalink
chore: add StateHashedNotification (#15395)
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Tinker <[email protected]>
  • Loading branch information
tinker-michaelj authored Sep 9, 2024
1 parent 3a62199 commit c7f12c7
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.swirlds.platform.listeners.ReconnectCompleteNotification;
import com.swirlds.platform.listeners.StateWriteToDiskCompleteNotification;
import com.swirlds.platform.system.state.notifications.IssNotification;
import com.swirlds.platform.system.state.notifications.StateHashedNotification;
import com.swirlds.platform.system.status.PlatformStatus;
import edu.umd.cs.findbugs.annotations.NonNull;

Expand All @@ -36,6 +37,14 @@ public interface AppNotifier {
@InputWireLabel("state written notification")
void sendStateWrittenToDiskNotification(@NonNull final StateWriteToDiskCompleteNotification notification);

/**
* Send a notification to the app that a state has been written to disk.
*
* @param notification the notification
*/
@InputWireLabel("state hashed notification")
void sendStateHashedNotification(@NonNull final StateHashedNotification notification);

/**
* Send a notification to the app that a reconnect has completed.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import com.swirlds.platform.system.state.notifications.IssListener;
import com.swirlds.platform.system.state.notifications.IssNotification;
import com.swirlds.platform.system.state.notifications.NewSignedStateListener;
import com.swirlds.platform.system.state.notifications.StateHashedListener;
import com.swirlds.platform.system.state.notifications.StateHashedNotification;
import com.swirlds.platform.system.status.PlatformStatus;
import edu.umd.cs.findbugs.annotations.NonNull;

Expand All @@ -42,6 +44,11 @@ public void sendStateWrittenToDiskNotification(@NonNull final StateWriteToDiskCo
notificationEngine.dispatch(StateWriteToDiskCompleteListener.class, notification);
}

@Override
public void sendStateHashedNotification(@NonNull final StateHashedNotification notification) {
notificationEngine.dispatch(StateHashedListener.class, notification);
}

/**
* {@inheritDoc}
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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.system.state.notifications;

import com.swirlds.common.notification.DispatchMode;
import com.swirlds.common.notification.DispatchModel;
import com.swirlds.common.notification.DispatchOrder;
import com.swirlds.common.notification.Listener;

/**
* A method that listens for the newly hashed states.
*/
@DispatchModel(mode = DispatchMode.SYNC, order = DispatchOrder.UNORDERED)
public interface StateHashedListener extends Listener<StateHashedNotification> {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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.system.state.notifications;

import static java.util.Objects.requireNonNull;

import com.swirlds.common.crypto.Hash;
import com.swirlds.common.notification.AbstractNotification;
import com.swirlds.common.notification.Notification;
import com.swirlds.platform.wiring.components.StateAndRound;
import edu.umd.cs.findbugs.annotations.NonNull;

/**
* A {@link Notification} that a state hash has been computed.
*/
public class StateHashedNotification extends AbstractNotification {
private final long roundNumber;
private final Hash hash;

/**
* Create a notification for a newly hashed state.
* @param stateAndRound the state and round that is now hashed
* @return a new notification
*/
public static StateHashedNotification from(@NonNull final StateAndRound stateAndRound) {
try (final var state = stateAndRound.reservedSignedState()) {
return new StateHashedNotification(
stateAndRound.round().getRoundNum(),
requireNonNull(state.get().getState().getHash()));
}
}

private StateHashedNotification(final long roundNumber, @NonNull final Hash hash) {
this.roundNumber = roundNumber;
this.hash = requireNonNull(hash);
}

public long round() {
return roundNumber;
}

public @NonNull Hash hash() {
return hash;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
import com.swirlds.platform.system.events.BirthRoundMigrationShim;
import com.swirlds.platform.system.events.UnsignedEvent;
import com.swirlds.platform.system.state.notifications.IssNotification;
import com.swirlds.platform.system.state.notifications.StateHashedNotification;
import com.swirlds.platform.system.status.PlatformStatus;
import com.swirlds.platform.system.status.PlatformStatusConfig;
import com.swirlds.platform.system.status.StatusActionSubmitter;
Expand Down Expand Up @@ -665,6 +666,9 @@ private void wire() {
hashedStateOutputWire.solderTo(hashLoggerWiring.getInputWire(HashLogger::logHashes));
hashedStateOutputWire.solderTo(stateSignerWiring.getInputWire(StateSigner::signState));
hashedStateAndRoundOutputWire.solderTo(issDetectorWiring.getInputWire(IssDetector::handleStateAndRound));
hashedStateAndRoundOutputWire
.buildTransformer("postHasher_notifier", "state and round", StateHashedNotification::from)
.solderTo(notifierWiring.getInputWire(AppNotifier::sendStateHashedNotification));

stateSignerWiring
.getOutputWire()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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.system.state.notifications;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.BDDMockito.given;

import com.swirlds.common.crypto.Hash;
import com.swirlds.platform.internal.ConsensusRound;
import com.swirlds.platform.state.MerkleRoot;
import com.swirlds.platform.state.signed.ReservedSignedState;
import com.swirlds.platform.state.signed.SignedState;
import com.swirlds.platform.wiring.components.StateAndRound;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class StateHashedNotificationTest {
private static final long ROUND = 123L;
private static final Hash HASH = new Hash(new byte[48]);

@Mock
private MerkleRoot merkleRoot;

@Mock
private SignedState signedState;

@Mock
private ConsensusRound round;

@Mock
private ReservedSignedState reservedSignedState;

@Test
void factoryWorksAsExpected() {
given(round.getRoundNum()).willReturn(ROUND);
given(reservedSignedState.get()).willReturn(signedState);
given(signedState.getState()).willReturn(merkleRoot);
given(merkleRoot.getHash()).willReturn(HASH);

final var notification = StateHashedNotification.from(new StateAndRound(reservedSignedState, round));

assertEquals(ROUND, notification.round());
assertEquals(HASH, notification.hash());
}
}

0 comments on commit c7f12c7

Please sign in to comment.