Skip to content

Commit

Permalink
chore: Reapply "FileService address book and node details" (#17543)
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Hess <matt.hess@swirldslabs.com>
  • Loading branch information
mhess-swl authored Jan 24, 2025
1 parent 4dbd47e commit c3cfc87
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 81 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023-2024 Hedera Hashgraph, LLC
* Copyright (C) 2023-2025 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -133,7 +133,8 @@ public SystemSetup(
*/
public void doGenesisSetup(@NonNull final Dispatch dispatch) {
final var systemContext = systemContextFor(dispatch);
fileService.createSystemEntities(systemContext);
final var nodeStore = dispatch.handleContext().storeFactory().readableStore(ReadableNodeStore.class);
fileService.createSystemEntities(systemContext, nodeStore);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@
import com.hedera.node.app.ids.EntityIdService;
import com.hedera.node.app.info.NodeInfoImpl;
import com.hedera.node.app.records.BlockRecordService;
import com.hedera.node.app.service.addressbook.AddressBookService;
import com.hedera.node.app.service.addressbook.ReadableNodeStore;
import com.hedera.node.app.service.addressbook.impl.AddressBookServiceImpl;
import com.hedera.node.app.service.addressbook.impl.ReadableNodeStoreImpl;
import com.hedera.node.app.service.consensus.impl.ConsensusServiceImpl;
import com.hedera.node.app.service.contract.impl.ContractServiceImpl;
import com.hedera.node.app.service.file.FileService;
Expand Down Expand Up @@ -391,8 +394,10 @@ private State genesisState(@NonNull final Map<String, String> overrides) {
NO_OP_METRICS,
startupNetworks);
final var writableStates = state.getWritableStates(FileService.NAME);
final var readableStates = state.getReadableStates(AddressBookService.NAME);
final var nodeStore = new ReadableNodeStoreImpl(readableStates);
final var files = writableStates.<FileID, File>get(V0490FileSchema.BLOBS_KEY);
genesisContentProviders(networkInfo, config).forEach((fileNum, provider) -> {
genesisContentProviders(nodeStore, config).forEach((fileNum, provider) -> {
final var fileId = createFileID(fileNum, config);
files.put(
fileId,
Expand All @@ -407,12 +412,12 @@ private State genesisState(@NonNull final Map<String, String> overrides) {
}

private Map<Long, Function<Configuration, Bytes>> genesisContentProviders(
@NonNull final NetworkInfo networkInfo, @NonNull final Configuration config) {
@NonNull final ReadableNodeStore nodeStore, @NonNull final Configuration config) {
final var genesisSchema = new V0490FileSchema();
final var filesConfig = config.getConfigData(FilesConfig.class);
return Map.of(
filesConfig.addressBook(), ignore -> genesisSchema.genesisAddressBook(networkInfo),
filesConfig.nodeDetails(), ignore -> genesisSchema.genesisNodeDetails(networkInfo),
filesConfig.addressBook(), ignore -> genesisSchema.nodeStoreAddressBook(nodeStore),
filesConfig.nodeDetails(), ignore -> genesisSchema.nodeStoreNodeDetails(nodeStore),
filesConfig.feeSchedules(), genesisSchema::genesisFeeSchedules,
filesConfig.exchangeRates(), genesisSchema::genesisExchangeRates,
filesConfig.networkProperties(), genesisSchema::genesisNetworkProperties,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2024 Hedera Hashgraph, LLC
* Copyright (C) 2020-2025 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -49,12 +49,13 @@ public void registerSchemas(@NonNull final SchemaRegistry registry) {
}

/**
* Creates the system files in the given genesis context.
* Creates the system files in the given genesis context and the nodeStore data.
*
* @param context the genesis context
* @param nodeStore the ReadableNodeStore
*/
public void createSystemEntities(@NonNull final SystemContext context) {
fileSchema.createGenesisAddressBookAndNodeDetails(context);
public void createSystemEntities(@NonNull final SystemContext context, @NonNull final ReadableNodeStore nodeStore) {
fileSchema.createGenesisAddressBookAndNodeDetails(context, nodeStore);
fileSchema.createGenesisFeeSchedule(context);
fileSchema.createGenesisExchangeRate(context);
fileSchema.createGenesisNetworkProperties(context);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2024 Hedera Hashgraph, LLC
* Copyright (C) 2022-2025 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -34,6 +34,7 @@
import com.hedera.hapi.node.transaction.Response;
import com.hedera.node.app.hapi.utils.CommonPbjConverters;
import com.hedera.node.app.hapi.utils.fee.FileFeeBuilder;
import com.hedera.node.app.service.addressbook.ReadableNodeStore;
import com.hedera.node.app.service.file.ReadableFileStore;
import com.hedera.node.app.service.file.impl.base.FileQueryBase;
import com.hedera.node.app.service.file.impl.schemas.V0490FileSchema;
Expand All @@ -45,7 +46,6 @@
import com.hederahashgraph.api.proto.java.FeeData;
import com.hederahashgraph.api.proto.java.ResponseType;
import com.swirlds.config.api.Configuration;
import com.swirlds.state.lifecycle.info.NetworkInfo;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.Map;
Expand All @@ -60,20 +60,16 @@
public class FileGetContentsHandler extends FileQueryBase {
private final FileFeeBuilder usageEstimator;
private final V0490FileSchema genesisSchema;
private final NetworkInfo networkInfo;

/**
* Constructs a {@link FileGetContentsHandler} with the given {@link FileFeeBuilder}.
* @param usageEstimator the file fee builder to be used for fee calculation
*/
@Inject
public FileGetContentsHandler(
@NonNull final FileFeeBuilder usageEstimator,
@NonNull final V0490FileSchema genesisSchema,
@NonNull final NetworkInfo networkInfo) {
@NonNull final FileFeeBuilder usageEstimator, @NonNull final V0490FileSchema genesisSchema) {
this.usageEstimator = requireNonNull(usageEstimator);
this.genesisSchema = requireNonNull(genesisSchema);
this.networkInfo = networkInfo;
}

@Override
Expand Down Expand Up @@ -102,10 +98,11 @@ public void validate(@NonNull final QueryContext context) throws PreCheckExcepti
public @NonNull Fees computeFees(@NonNull QueryContext queryContext) {
final var query = queryContext.query();
final var fileStore = queryContext.createStore(ReadableFileStore.class);
final var nodeStore = queryContext.createStore(ReadableNodeStore.class);
final var op = query.fileGetContentsOrThrow();
final var fileId = op.fileIDOrElse(FileID.DEFAULT);
final var responseType = op.headerOrElse(QueryHeader.DEFAULT).responseType();
final FileContents fileContents = contentFile(fileId, fileStore, queryContext.configuration());
final FileContents fileContents = contentFile(fileId, fileStore, queryContext.configuration(), nodeStore);
return queryContext
.feeCalculator()
.legacyCalculate(sigValueObj ->
Expand All @@ -117,14 +114,15 @@ public void validate(@NonNull final QueryContext context) throws PreCheckExcepti
requireNonNull(header);
final var query = context.query();
final var fileStore = context.createStore(ReadableFileStore.class);
final var nodeStore = context.createStore(ReadableNodeStore.class);
final var op = query.fileGetContentsOrThrow();
final var responseBuilder = FileGetContentsResponse.newBuilder();
final var fileId = op.fileIDOrThrow();

final var responseType = op.headerOrElse(QueryHeader.DEFAULT).responseType();
responseBuilder.header(header);
if (header.nodeTransactionPrecheckCode() == OK && responseType != COST_ANSWER) {
final var content = contentFile(fileId, fileStore, context.configuration());
final var content = contentFile(fileId, fileStore, context.configuration(), nodeStore);
if (content == null) {
responseBuilder.header(header.copyBuilder()
.nodeTransactionPrecheckCode(INVALID_FILE_ID)
Expand All @@ -143,18 +141,20 @@ public void validate(@NonNull final QueryContext context) throws PreCheckExcepti
* @param fileID the file to get information about
* @param fileStore the file store
* @param config the configuration
* @param nodeStore the ReadableNodeStore
* @return the content about the file
*/
private @Nullable FileContents contentFile(
@NonNull final FileID fileID,
@NonNull final ReadableFileStore fileStore,
@NonNull final Configuration config) {
@NonNull final Configuration config,
@NonNull final ReadableNodeStore nodeStore) {
final var meta = fileStore.getFileMetadata(fileID);
if (meta == null) {
if (notGenesisCreation(fileID, config)) {
return null;
} else {
final var genesisContent = genesisContentProviders(config)
final var genesisContent = genesisContentProviders(config, nodeStore)
.getOrDefault(fileID.fileNum(), ignore -> EMPTY)
.apply(config);
return new FileContents(fileID, genesisContent);
Expand All @@ -167,11 +167,12 @@ public void validate(@NonNull final QueryContext context) throws PreCheckExcepti
}
}

private Map<Long, Function<Configuration, Bytes>> genesisContentProviders(@NonNull final Configuration config) {
private Map<Long, Function<Configuration, Bytes>> genesisContentProviders(
@NonNull final Configuration config, @NonNull final ReadableNodeStore nodeStore) {
final var filesConfig = config.getConfigData(FilesConfig.class);
return Map.of(
filesConfig.addressBook(), ignore -> genesisSchema.genesisAddressBook(networkInfo),
filesConfig.nodeDetails(), ignore -> genesisSchema.genesisNodeDetails(networkInfo),
filesConfig.addressBook(), ignore -> genesisSchema.nodeStoreAddressBook(nodeStore),
filesConfig.nodeDetails(), ignore -> genesisSchema.nodeStoreNodeDetails(nodeStore),
filesConfig.feeSchedules(), genesisSchema::genesisFeeSchedules,
filesConfig.exchangeRates(), genesisSchema::genesisExchangeRates,
filesConfig.networkProperties(), genesisSchema::genesisNetworkProperties,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
import com.hedera.hapi.node.transaction.ThrottleDefinitions;
import com.hedera.hapi.node.transaction.TransactionBody;
import com.hedera.node.app.service.addressbook.ReadableNodeStore;
import com.hedera.node.app.service.addressbook.impl.schemas.V053AddressBookSchema;
import com.hedera.node.app.spi.workflows.SystemContext;
import com.hedera.node.config.ConfigProvider;
import com.hedera.node.config.data.BootstrapConfig;
Expand All @@ -64,8 +63,6 @@
import com.swirlds.state.lifecycle.MigrationContext;
import com.swirlds.state.lifecycle.Schema;
import com.swirlds.state.lifecycle.StateDefinition;
import com.swirlds.state.lifecycle.info.NetworkInfo;
import com.swirlds.state.lifecycle.info.NodeInfo;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.io.ByteArrayInputStream;
Expand Down Expand Up @@ -166,9 +163,9 @@ public void migrate(@NonNull final MigrationContext ctx) {
// ================================================================================================================
// Creates and loads the Address Book into state

public void createGenesisAddressBookAndNodeDetails(@NonNull final SystemContext systemContext) {
public void createGenesisAddressBookAndNodeDetails(
@NonNull final SystemContext systemContext, @NonNull final ReadableNodeStore nodeStore) {
requireNonNull(systemContext);
final var networkInfo = systemContext.networkInfo();
final var filesConfig = systemContext.configuration().getConfigData(FilesConfig.class);
final var bootstrapConfig = systemContext.configuration().getConfigData(BootstrapConfig.class);

Expand All @@ -184,7 +181,7 @@ public void createGenesisAddressBookAndNodeDetails(@NonNull final SystemContext
systemContext.dispatchCreation(
TransactionBody.newBuilder()
.fileCreate(FileCreateTransactionBody.newBuilder()
.contents(genesisAddressBook(networkInfo))
.contents(nodeStoreAddressBook(nodeStore))
.keys(masterKey)
.expirationTime(maxLifetimeExpiry(systemContext))
.build())
Expand All @@ -195,44 +192,14 @@ public void createGenesisAddressBookAndNodeDetails(@NonNull final SystemContext
systemContext.dispatchCreation(
TransactionBody.newBuilder()
.fileCreate(FileCreateTransactionBody.newBuilder()
.contents(genesisNodeDetails(networkInfo))
.contents(nodeStoreNodeDetails(nodeStore))
.keys(masterKey)
.expirationTime(maxLifetimeExpiry(systemContext))
.build())
.build(),
nodeInfoFileNum);
}

public Bytes genesisAddressBook(@NonNull final NetworkInfo networkInfo) {
final var nodeAddresses = networkInfo.addressBook().stream()
.sorted(Comparator.comparingLong(NodeInfo::nodeId))
.map(nodeInfo -> NodeAddress.newBuilder()
.nodeId(nodeInfo.nodeId())
.nodeAccountId(nodeInfo.accountId())
.rsaPubKey(nodeInfo.hexEncodedPublicKey())
.serviceEndpoint(V053AddressBookSchema.endpointFor("1.0.0.0", 1))
.build())
.toList();
return NodeAddressBook.PROTOBUF.toBytes(
NodeAddressBook.newBuilder().nodeAddress(nodeAddresses).build());
}

public Bytes genesisNodeDetails(@NonNull final NetworkInfo networkInfo) {
final var nodeDetails = networkInfo.addressBook().stream()
.sorted(Comparator.comparingLong(NodeInfo::nodeId))
.map(nodeInfo -> NodeAddress.newBuilder()
.stake(nodeInfo.weight())
.nodeAccountId(nodeInfo.accountId())
.nodeId(nodeInfo.nodeId())
.rsaPubKey(nodeInfo.hexEncodedPublicKey())
.serviceEndpoint(V053AddressBookSchema.endpointFor("1.0.0.0", 1))
.build())
.toList();

return NodeAddressBook.PROTOBUF.toBytes(
NodeAddressBook.newBuilder().nodeAddress(nodeDetails).build());
}

public void updateAddressBookAndNodeDetailsAfterFreeze(
@NonNull final SystemContext systemContext, @NonNull final ReadableNodeStore nodeStore) {
requireNonNull(systemContext);
Expand Down Expand Up @@ -262,7 +229,7 @@ public static void dispatchSynthFileUpdate(
.build()));
}

private Bytes nodeStoreNodeDetails(@NonNull final ReadableNodeStore nodeStore) {
public Bytes nodeStoreNodeDetails(@NonNull final ReadableNodeStore nodeStore) {
final var nodeDetails = new ArrayList<NodeAddress>();
StreamSupport.stream(Spliterators.spliterator(nodeStore.keys(), nodeStore.sizeOfState(), DISTINCT), false)
.mapToLong(EntityNumber::number)
Expand All @@ -288,7 +255,7 @@ private Bytes getHexStringBytesFromBytes(final Bytes rawBytes) {
return Bytes.wrap(Normalizer.normalize(hexString, Normalizer.Form.NFD).getBytes(UTF_8));
}

private Bytes nodeStoreAddressBook(@NonNull final ReadableNodeStore nodeStore) {
public Bytes nodeStoreAddressBook(@NonNull final ReadableNodeStore nodeStore) {
final var nodeAddresses = new ArrayList<NodeAddress>();
StreamSupport.stream(Spliterators.spliterator(nodeStore.keys(), nodeStore.sizeOfState(), DISTINCT), false)
.mapToLong(EntityNumber::number)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
requires transitive com.hedera.node.app.spi;
requires transitive com.hedera.node.config;
requires transitive com.hedera.node.hapi;
requires transitive com.hedera.pbj.runtime;
requires transitive com.swirlds.config.api;
requires transitive com.swirlds.state.api;
requires transitive com.hedera.pbj.runtime;
requires transitive dagger;
requires transitive static java.compiler; // javax.annotation.processing.Generated
requires transitive java.compiler; // javax.annotation.processing.Generated
requires transitive javax.inject;
requires com.hedera.node.app.service.addressbook.impl;
requires com.swirlds.common;
requires com.fasterxml.jackson.databind;
requires com.google.protobuf;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023-2024 Hedera Hashgraph, LLC
* Copyright (C) 2023-2025 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -49,7 +49,6 @@
import com.hedera.node.app.spi.workflows.QueryContext;
import com.hedera.node.config.data.FilesConfig;
import com.hedera.pbj.runtime.io.buffer.Bytes;
import com.swirlds.state.lifecycle.info.NetworkInfo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand All @@ -68,14 +67,11 @@ class FileGetContentsHandlerTest extends FileTestBase {
@Mock
private V0490FileSchema genesisSchema;

@Mock
private NetworkInfo networkInfo;

private FileGetContentsHandler subject;

@BeforeEach
void setUp() {
subject = new FileGetContentsHandler(usageEstimator, genesisSchema, networkInfo);
subject = new FileGetContentsHandler(usageEstimator, genesisSchema);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
* Copyright (C) 2024-2025 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -44,4 +44,19 @@ private GroupingVerbs() {
public static SysFileLookups getSystemFiles(@NonNull final Consumer<Map<FileID, Bytes>> observer) {
return new SysFileLookups(fileNum -> true, observer);
}

/**
* Returns a utility operation to retrieve the contents of specific system files and pass them to an observer.
*
* @param sysfileNub the system file number
* @param observer the consumer of the system file contents
* @return the utility operation
*/
public static SysFileLookups getSystemFiles(final long sysfileNub, @NonNull final Consumer<Bytes> observer) {
final Consumer<Map<FileID, Bytes>> temp = map -> {
final Bytes contents = map.get(new FileID(0, 0, sysfileNub));
observer.accept(contents);
};
return new SysFileLookups(fileNum -> fileNum == sysfileNub, temp);
}
}
Loading

0 comments on commit c3cfc87

Please sign in to comment.