├── version.txt ├── common ├── src │ ├── test │ │ ├── resources │ │ │ ├── invalid1.gz │ │ │ ├── valid1.blk │ │ │ ├── valid2.blk │ │ │ ├── valid1.txt.gz │ │ │ └── valid2.txt.gz │ │ └── java │ │ │ └── org │ │ │ └── hiero │ │ │ └── block │ │ │ └── common │ │ │ └── utils │ │ │ └── StringUtilitiesTest.java │ └── main │ │ └── java │ │ ├── module-info.java │ │ └── org │ │ └── hiero │ │ └── block │ │ └── common │ │ ├── constants │ │ └── StringsConstants.java │ │ ├── hasher │ │ └── Hashes.java │ │ └── utils │ │ ├── StringUtilities.java │ │ └── ChunkUtils.java └── build.gradle.kts ├── protobuf-sources ├── .gitignore └── src │ └── main │ ├── java │ └── module-info.java │ └── proto │ └── block-node │ └── api │ ├── reconnect_service.proto │ └── shared_message_types.proto ├── .idea └── .gitignore ├── gradle ├── toolchain-versions.properties ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── modules.properties └── aggregation │ └── build.gradle.kts ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── 01-Story-Template.yml │ └── 03-Bug-Template.yml ├── pull_request_template.md ├── dependabot.yml └── release.yaml ├── tools-and-tests ├── simulator │ ├── src │ │ ├── test │ │ │ ├── resources │ │ │ │ └── block-0.0.3-blk │ │ │ │ │ ├── notABlock.txt │ │ │ │ │ ├── 000000000000000000000000000000000000.blk │ │ │ │ │ ├── 000000000000000000000000000000000001.blk │ │ │ │ │ ├── 000000000000000000000000000000000002.blk │ │ │ │ │ ├── 000000000000000000000000000000000003.blk │ │ │ │ │ ├── 000000000000000000000000000000000004.blk │ │ │ │ │ ├── 000000000000000000000000000000000005.blk │ │ │ │ │ ├── 000000000000000000000000000000000006.blk │ │ │ │ │ ├── 000000000000000000000000000000000007.blk │ │ │ │ │ └── 000000000000000000000000000000000008.blk │ │ │ └── java │ │ │ │ └── org │ │ │ │ └── hiero │ │ │ │ └── block │ │ │ │ └── simulator │ │ │ │ ├── config │ │ │ │ ├── logging │ │ │ │ │ └── TestSecretConfig.java │ │ │ │ └── types │ │ │ │ │ ├── GenerationModeTest.java │ │ │ │ │ └── StreamingModeTest.java │ │ │ │ ├── metrics │ │ │ │ └── MetricsInjectionModuleTest.java │ │ │ │ ├── generator │ │ │ │ └── itemhandler │ │ │ │ │ ├── SignedTransactionHandlerTest.java │ │ │ │ │ └── EventHeaderHandlerTest.java │ │ │ │ └── mode │ │ │ │ └── PublisherServerModeHandlerTest.java │ │ ├── main │ │ │ └── java │ │ │ │ ├── org │ │ │ │ └── hiero │ │ │ │ │ └── block │ │ │ │ │ └── simulator │ │ │ │ │ ├── config │ │ │ │ │ ├── logging │ │ │ │ │ │ ├── ConfigurationLogging.java │ │ │ │ │ │ └── Loggable.java │ │ │ │ │ ├── types │ │ │ │ │ │ ├── GenerationMode.java │ │ │ │ │ │ ├── SimulatorMode.java │ │ │ │ │ │ ├── MidBlockFailType.java │ │ │ │ │ │ ├── StreamingMode.java │ │ │ │ │ │ └── EndStreamMode.java │ │ │ │ │ ├── data │ │ │ │ │ │ ├── GrpcConfig.java │ │ │ │ │ │ ├── ConsumerConfig.java │ │ │ │ │ │ └── SimulatorStartupDataConfig.java │ │ │ │ │ └── SimulatorConfigExtension.java │ │ │ │ │ ├── metrics │ │ │ │ │ ├── MetricsService.java │ │ │ │ │ ├── MetricsInjectionModule.java │ │ │ │ │ └── MetricsServiceImpl.java │ │ │ │ │ ├── Constants.java │ │ │ │ │ ├── startup │ │ │ │ │ └── StartupDataInjectionModule.java │ │ │ │ │ ├── exception │ │ │ │ │ └── BlockSimulatorParsingException.java │ │ │ │ │ ├── grpc │ │ │ │ │ └── PublishStreamGrpcServer.java │ │ │ │ │ └── generator │ │ │ │ │ ├── itemhandler │ │ │ │ │ ├── ItemHandler.java │ │ │ │ │ └── EventHeaderHandler.java │ │ │ │ │ ├── BlockStreamManager.java │ │ │ │ │ └── GeneratorInjectionModule.java │ │ │ │ └── module-info.java │ │ └── testFixtures │ │ │ └── java │ │ │ ├── module-info.java │ │ │ └── org │ │ │ └── hiero │ │ │ └── block │ │ │ └── simulator │ │ │ └── fixtures │ │ │ └── generator │ │ │ └── TestBlockStreamManager.java │ └── docker │ │ ├── dashboards │ │ └── provisioner.yaml │ │ ├── datasources.yml │ │ ├── simulator-prometheus.yml │ │ ├── loki-config.yaml │ │ ├── Dockerfile │ │ ├── simulator-promtail-config.yaml │ │ └── update-env.sh ├── suites │ └── src │ │ └── main │ │ ├── resources │ │ ├── block-nodes.json │ │ └── app-test.properties │ │ └── java │ │ ├── org │ │ └── hiero │ │ │ └── block │ │ │ └── suites │ │ │ ├── BlockNodeContainerConfig.java │ │ │ ├── block │ │ │ └── access │ │ │ │ └── BlockAccessTestSuites.java │ │ │ ├── metrics │ │ │ └── MetricsTestSuites.java │ │ │ ├── server │ │ │ └── status │ │ │ │ └── ServerStatusTestSuites.java │ │ │ ├── verification │ │ │ └── BlockVerificationTestSuites.java │ │ │ ├── utils │ │ │ └── ServerStatusUtils.java │ │ │ ├── persistence │ │ │ └── DataPersistenceTestSuites.java │ │ │ ├── publisher │ │ │ └── PublisherTestSuites.java │ │ │ ├── subscriber │ │ │ └── SubscriberTestSuites.java │ │ │ └── grpc │ │ │ └── GrpcTestSuites.java │ │ └── module-info.java ├── scripts │ └── node-operations │ │ └── sample.env ├── k6 │ ├── package.json │ ├── data.json │ ├── package-lock.json │ ├── lib │ │ └── grpc.js │ └── average-load │ │ └── bn-server-status.js ├── tools │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ ├── clientDefaultConfig.json │ │ │ └── serverDefaultConfig.json │ │ │ └── java │ │ │ └── org │ │ │ └── hiero │ │ │ └── block │ │ │ └── tools │ │ │ ├── commands │ │ │ └── record2blocks │ │ │ │ └── model │ │ │ │ └── ChainFileAndCount.java │ │ │ ├── config │ │ │ └── proto │ │ │ │ └── network_capacity_config.proto │ │ │ └── BlockStreamTool.java │ └── docker │ │ ├── update-env.sh │ │ ├── docker-build.sh │ │ ├── Dockerfile │ │ └── docker-compose.yml └── protobuf-protoc │ ├── build.gradle.kts │ └── src │ └── main │ └── java │ └── module-info.java ├── charts ├── .gitignore ├── block-node-server │ ├── values-overrides │ │ ├── enable-observability.yaml │ │ ├── mid-size.yaml │ │ ├── backfill.yaml │ │ ├── rfh-values.yaml │ │ ├── mini.yaml │ │ ├── nano.yaml │ │ ├── host-paths.yaml │ │ └── lfh-values.yaml │ ├── templates │ │ ├── secret.yaml │ │ ├── configmap.yaml │ │ ├── configmap-logging.yaml │ │ ├── serviceaccount.yaml │ │ ├── configmap-block-node-sources.yaml │ │ ├── servicemonitor.yaml │ │ ├── service.yaml │ │ ├── NOTES.txt │ │ ├── grafana-datasource.yaml │ │ ├── service-loadbalancer.yaml │ │ └── grafana-dashboard-configmap.yaml │ ├── .helmignore │ └── Chart.yaml └── blockstream-simulator │ ├── values-overrides │ └── consumer.yaml │ ├── templates │ ├── NOTES.txt │ ├── configmap.yaml │ ├── secret.yaml │ └── pvc-simulator-data.yaml │ ├── .helmignore │ ├── Chart.yaml │ └── values.yaml ├── ct.yaml ├── block-node ├── app │ ├── docker │ │ ├── .dockerignore │ │ ├── backfill-sources.json │ │ ├── metrics │ │ │ ├── prometheus.yml │ │ │ ├── dashboards │ │ │ │ └── provisioner.yaml │ │ │ └── datasources │ │ │ │ └── datasources.yml │ │ ├── README.md │ │ ├── docker-build.sh │ │ ├── loki-config.yaml │ │ └── promtail-config.yaml │ └── src │ │ ├── testFixtures │ │ ├── resources │ │ │ └── test-blocks │ │ │ │ ├── HAPI-0-66-0 │ │ │ │ └── 000000000000000000000000000000000010.blk.gz │ │ │ │ └── HAPI-0-68-0 │ │ │ │ └── 000000000000000000000000000000000014.blk.gz │ │ └── java │ │ │ ├── org │ │ │ └── hiero │ │ │ │ └── block │ │ │ │ └── node │ │ │ │ └── app │ │ │ │ └── fixtures │ │ │ │ ├── plugintest │ │ │ │ ├── NoBlocksHistoricalBlockFacility.java │ │ │ │ ├── NoOpServiceBuilder.java │ │ │ │ └── TestHealthFacility.java │ │ │ │ ├── async │ │ │ │ └── ScheduledBlockingExecutor.java │ │ │ │ ├── blocks │ │ │ │ └── MinimalBlockAccessor.java │ │ │ │ └── TestUtils.java │ │ │ └── module-info.java │ │ ├── test │ │ ├── resources │ │ │ └── app-test.properties │ │ └── java │ │ │ └── org │ │ │ └── hiero │ │ │ └── block │ │ │ └── node │ │ │ └── app │ │ │ └── logging │ │ │ └── TestSecretConfig.java │ │ └── main │ │ ├── resources │ │ └── app.properties │ │ └── java │ │ ├── module-info.java │ │ └── org │ │ └── hiero │ │ └── block │ │ └── node │ │ └── app │ │ └── ServiceBuilderImpl.java ├── app-config │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ └── app.properties │ │ │ └── java │ │ │ │ ├── module-info.java │ │ │ │ └── org │ │ │ │ └── hiero │ │ │ │ └── block │ │ │ │ └── node │ │ │ │ └── app │ │ │ │ └── config │ │ │ │ └── node │ │ │ │ └── NodeConfig.java │ │ └── test │ │ │ ├── resources │ │ │ └── app-test.properties │ │ │ └── java │ │ │ └── org │ │ │ └── hiero │ │ │ └── block │ │ │ └── node │ │ │ └── app │ │ │ └── config │ │ │ └── TestSecretConfig.java │ └── build.gradle.kts ├── spi-plugins │ ├── src │ │ └── main │ │ │ └── java │ │ │ ├── org │ │ │ └── hiero │ │ │ │ └── block │ │ │ │ └── node │ │ │ │ └── spi │ │ │ │ ├── blockmessaging │ │ │ │ ├── NewestBlockKnownToNetworkNotification.java │ │ │ │ ├── BackfilledBlockNotification.java │ │ │ │ ├── PersistedNotification.java │ │ │ │ ├── BlockSource.java │ │ │ │ ├── VerificationNotification.java │ │ │ │ ├── NoBackPressureBlockItemHandler.java │ │ │ │ ├── BlockItemHandler.java │ │ │ │ └── BlockNotificationHandler.java │ │ │ │ ├── ServiceLoaderFunction.java │ │ │ │ ├── ServiceBuilder.java │ │ │ │ ├── historicalblocks │ │ │ │ └── HistoricalBlockFacility.java │ │ │ │ └── health │ │ │ │ └── HealthFacility.java │ │ │ └── module-info.java │ └── build.gradle.kts ├── backfill │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ └── block-nodes.json │ │ └── main │ │ │ └── java │ │ │ ├── org │ │ │ └── hiero │ │ │ │ └── block │ │ │ │ └── node │ │ │ │ └── backfill │ │ │ │ └── client │ │ │ │ └── proto │ │ │ │ └── block_node_source.proto │ │ │ └── module-info.java │ └── build.gradle.kts ├── verification │ ├── src │ │ └── main │ │ │ └── java │ │ │ ├── org │ │ │ └── hiero │ │ │ │ └── block │ │ │ │ └── node │ │ │ │ └── verification │ │ │ │ ├── VerificationConfig.java │ │ │ │ └── session │ │ │ │ └── VerificationSession.java │ │ │ └── module-info.java │ └── build.gradle.kts ├── health │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── module-info.java │ └── build.gradle.kts ├── block-access-service │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── module-info.java │ └── build.gradle.kts ├── server-status │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── module-info.java │ └── build.gradle.kts ├── base │ ├── src │ │ └── main │ │ │ └── java │ │ │ ├── module-info.java │ │ │ └── org │ │ │ └── hiero │ │ │ └── block │ │ │ └── node │ │ │ └── base │ │ │ ├── s3 │ │ │ ├── S3ClientException.java │ │ │ └── S3ClientInitializationException.java │ │ │ └── Loggable.java │ └── build.gradle.kts ├── stream-publisher │ ├── src │ │ └── main │ │ │ └── java │ │ │ ├── org │ │ │ └── hiero │ │ │ │ └── block │ │ │ │ └── node │ │ │ │ └── stream │ │ │ │ └── publisher │ │ │ │ └── PublisherConfig.java │ │ │ └── module-info.java │ └── build.gradle.kts ├── s3-archive │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── module-info.java ├── stream-subscriber │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ ├── module-info.java │ │ └── org │ │ └── hiero │ │ └── block │ │ └── node │ │ └── stream │ │ └── subscriber │ │ └── SubscriberConfig.java ├── blocks-file-recent │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ ├── module-info.java │ │ └── org │ │ └── hiero │ │ └── block │ │ └── node │ │ └── blocks │ │ └── files │ │ └── recent │ │ └── FilesRecentConfig.java ├── facility-messaging │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ ├── module-info.java │ │ └── org │ │ └── hiero │ │ └── block │ │ └── node │ │ └── messaging │ │ └── BlockItemBatchRingEvent.java ├── blocks-file-historic │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── module-info.java ├── README.md └── protobuf-pbj │ └── build.gradle.kts ├── docs ├── assets │ ├── 00036-consumer-registration.png │ ├── 00036-producer-registration.png │ ├── 00036-refactor-demo-disruptor.png │ └── 00036-demo-disruptor-class-diagram.png ├── design │ ├── how-to-design-doc.md │ ├── communication-protocol │ │ └── README.md │ └── design-doc-template.md ├── overview.md ├── configuration.md ├── block-node │ ├── README.md │ └── architecture │ │ └── data-flow.md └── tools │ └── quickstart.md ├── SECURITY.md ├── .editorconfig ├── gradle.properties ├── tool.sh ├── codecov.yml ├── .gitignore └── settings.gradle.kts /version.txt: -------------------------------------------------------------------------------- 1 | 0.26.0-SNAPSHOT -------------------------------------------------------------------------------- /common/src/test/resources/invalid1.gz: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /protobuf-sources/.gitignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | -------------------------------------------------------------------------------- /common/src/test/resources/valid1.blk: -------------------------------------------------------------------------------- 1 | valid1blk -------------------------------------------------------------------------------- /common/src/test/resources/valid2.blk: -------------------------------------------------------------------------------- 1 | valid2blk -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /gradle/toolchain-versions.properties: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | jdk=21.0.7 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | blank_issues_enabled: true 3 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/notABlock.txt: -------------------------------------------------------------------------------- 1 | not a block, just ignore this file. 2 | -------------------------------------------------------------------------------- /charts/.gitignore: -------------------------------------------------------------------------------- 1 | */out 2 | out 3 | /hedera-block-node/Chart.lock 4 | /hedera-block-node/charts/* 5 | */charts/*.tgz 6 | *.lock 7 | -------------------------------------------------------------------------------- /ct.yaml: -------------------------------------------------------------------------------- 1 | check-version-increment: false 2 | target-branch: main 3 | validate-maintainers: false 4 | install: 5 | timeout: 600 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /block-node/app/docker/.dockerignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.md 3 | *.sw* 4 | *.csv 5 | 6 | mvnw* 7 | LICENSE* 8 | 9 | .java-version 10 | -------------------------------------------------------------------------------- /protobuf-sources/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | module org.hiero.block.protobuf.sources {} 3 | -------------------------------------------------------------------------------- /block-node/app-config/src/main/resources/app.properties: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | prometheus.endpointPortNumber=16007 4 | -------------------------------------------------------------------------------- /common/src/test/resources/valid1.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/common/src/test/resources/valid1.txt.gz -------------------------------------------------------------------------------- /common/src/test/resources/valid2.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/common/src/test/resources/valid2.txt.gz -------------------------------------------------------------------------------- /docs/assets/00036-consumer-registration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/docs/assets/00036-consumer-registration.png -------------------------------------------------------------------------------- /docs/assets/00036-producer-registration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/docs/assets/00036-producer-registration.png -------------------------------------------------------------------------------- /docs/assets/00036-refactor-demo-disruptor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/docs/assets/00036-refactor-demo-disruptor.png -------------------------------------------------------------------------------- /docs/assets/00036-demo-disruptor-class-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/docs/assets/00036-demo-disruptor-class-diagram.png -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/resources/block-nodes.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [ 3 | { "address": "block-node-source", "port": 40840, "priority": 1 } 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /block-node/app-config/src/test/resources/app-test.properties: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | # Test Properties File 4 | prometheus.endpointEnabled=false 5 | -------------------------------------------------------------------------------- /charts/block-node-server/values-overrides/enable-observability.yaml: -------------------------------------------------------------------------------- 1 | kubepromstack: 2 | enabled: true 3 | 4 | loki: 5 | enabled: true 6 | 7 | promtail: 8 | enabled: true 9 | -------------------------------------------------------------------------------- /tools-and-tests/scripts/node-operations/sample.env: -------------------------------------------------------------------------------- 1 | NAMESPACE= 2 | RELEASE= 3 | VERSION= 4 | POD=-block-node-server-0 5 | -------------------------------------------------------------------------------- /block-node/app/docker/backfill-sources.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [ 3 | { 4 | "address": "host.docker.internal", 5 | "port": 40841, 6 | "priority": 1 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /block-node/app/docker/metrics/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 1s 3 | 4 | scrape_configs: 5 | - job_name: 'local' 6 | static_configs: 7 | - targets: ['block-node-server:16007', 'cadvisor:8080'] 8 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Reviewer Notes 2 | 3 | ## Related Issue(s) 4 | Use keywords `Fix, Fixes, Fixed, Close, Closes, Closed, Resolve, Resolves, Resolved` 5 | to connect an issue to be closed by this pull request. 6 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please do not file a public ticket mentioning the vulnerability. To report a vulnerability, please send an email to [security@hashgraph.com](security@hashgraph.com). 6 | -------------------------------------------------------------------------------- /tools-and-tests/k6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@hiero-ledger/block-node-k6", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "test": "./run-k6-tests.sh" 6 | }, 7 | "devDependencies": { 8 | "@types/k6": "^1.4.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tools-and-tests/k6/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "configs": [{ 3 | "blockNodeUrl": "localhost:40840", 4 | "protobufPath": "./../k6-proto", 5 | "smokeTestConfigs": { 6 | "numOfBlocksToStream": 10 7 | } 8 | }] 9 | } 10 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000000.blk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000000.blk -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000001.blk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000001.blk -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000002.blk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000002.blk -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000003.blk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000003.blk -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000004.blk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000004.blk -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000005.blk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000005.blk -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000006.blk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000006.blk -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000007.blk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000007.blk -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000008.blk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/tools-and-tests/simulator/src/test/resources/block-0.0.3-blk/000000000000000000000000000000000008.blk -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/resources/app-test.properties: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Test Properties File 3 | files.recent.liveRootPath=build/tmp/data/liveRootPath 4 | files.historic.rootPath=build/tmp/data/historic 5 | prometheus.endpointEnabled=false 6 | -------------------------------------------------------------------------------- /block-node/app/src/testFixtures/resources/test-blocks/HAPI-0-66-0/000000000000000000000000000000000010.blk.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/block-node/app/src/testFixtures/resources/test-blocks/HAPI-0-66-0/000000000000000000000000000000000010.blk.gz -------------------------------------------------------------------------------- /block-node/app/src/testFixtures/resources/test-blocks/HAPI-0-68-0/000000000000000000000000000000000014.blk.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-block-node/HEAD/block-node/app/src/testFixtures/resources/test-blocks/HAPI-0-68-0/000000000000000000000000000000000014.blk.gz -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/blockmessaging/NewestBlockKnownToNetworkNotification.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.blockmessaging; 3 | 4 | public record NewestBlockKnownToNetworkNotification(long blockNumber) {} 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 4 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | -------------------------------------------------------------------------------- /charts/blockstream-simulator/values-overrides/consumer.yaml: -------------------------------------------------------------------------------- 1 | # 2 consumers 2 | replicas: 2 3 | 4 | simulator: 5 | config: 6 | GRPC_SERVER_ADDRESS: "my-bn-block-node-helm-chart" 7 | GRPC_PORT: 40840 8 | BLOCK_STREAM_SIMULATOR_MODE: "CONSUMER" 9 | SIMULATOR_STARTUP_DATA_ENABLED: "false" 10 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/blockmessaging/BackfilledBlockNotification.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.blockmessaging; 3 | 4 | public record BackfilledBlockNotification(long blockNumber, org.hiero.block.internal.BlockUnparsed block) {} 5 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 3 | 4 | # Enable Gradle Caching 5 | org.gradle.configuration-cache=true 6 | org.gradle.caching=true 7 | org.gradle.parallel=true 8 | 9 | # Disable publish signing by default 10 | publishSigningEnabled=false 11 | -------------------------------------------------------------------------------- /block-node/app/src/test/resources/app-test.properties: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | # Test Properties File 4 | prometheus.endpointEnabled=false 5 | mediator.ringBufferSize=1024 6 | notifier.ringBufferSize=1024 7 | files.recent.liveRootPath=build/tmp/data/liveRootPath 8 | files.historic.rootPath=build/tmp/data/historic 9 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/blockmessaging/PersistedNotification.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.blockmessaging; 3 | 4 | public record PersistedNotification( 5 | long blockNumber, boolean succeeded, int blockProviderPriority, BlockSource blockSource) {} 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /charts/blockstream-simulator/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | BlockStream Simulator Chart has been deployed successfully. 2 | The simulator does not expose any services or API, but it automatically starts to work with the provided documentation. 3 | 4 | The configuration can be overridden by providing a custom values.yaml with the following dictionary: 5 | simulator.config 6 | -------------------------------------------------------------------------------- /block-node/backfill/src/test/resources/block-nodes.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [ 3 | { "address": "localhost", "port": 40801, "priority": 1 }, 4 | { "address": "node2.example.com", "port": 40902, "priority": 2 }, 5 | { "address": "node3.example.com", "port": 40903, "priority": 2 }, 6 | { "address": "node4.example.com", "port": 40904, "priority": 3 } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /gradle/modules.properties: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | # Jars that are not yet modules used in the 'tools' project 4 | com.google.api.gax=com.google.api:gax 5 | com.google.auth.oauth2=com.google.auth:google-auth-library-oauth2-http 6 | com.google.cloud.core=com.google.cloud:google-cloud-core 7 | com.google.cloud.storage=com.google.cloud:google-cloud-storage 8 | -------------------------------------------------------------------------------- /charts/blockstream-simulator/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | SPDX-License-Identifier: Apache-2.0 3 | */}} 4 | 5 | apiVersion: v1 6 | kind: ConfigMap 7 | metadata: 8 | name: {{ include "blockstream-simulator-chart.fullname" . }}-config 9 | data: 10 | {{- range $key, $value := .Values.simulator.config }} 11 | {{ $key }}: {{ $value | quote }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /charts/blockstream-simulator/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | SPDX-License-Identifier: Apache-2.0 3 | */}} 4 | 5 | apiVersion: v1 6 | kind: Secret 7 | metadata: 8 | name: {{ include "blockstream-simulator-chart.fullname" . }}-secret 9 | type: Opaque 10 | data: 11 | {{- range $key, $value := .Values.simulator.secret }} 12 | {{ $key }}: {{ $value | b64enc }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /block-node/app/docker/README.md: -------------------------------------------------------------------------------- 1 | This folder contains file that are used to start the block node server as docker container. 2 | All docker workflows are defined with a corresponding gradle task. No script or file in this folder should be called 'by hand'. 3 | 4 | Gradle tasks are of group `docker` 5 | - updateDockerEnv 6 | - createDockerImage 7 | - startDockerContainer 8 | - stopDockerContainer 9 | -------------------------------------------------------------------------------- /block-node/app/docker/metrics/dashboards/provisioner.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: 'default' 5 | orgId: 1 6 | folder: '' 7 | folderUid: '' 8 | type: file 9 | disableDeletion: false 10 | updateIntervalSeconds: 10 11 | allowUiUpdates: true 12 | options: 13 | path: /etc/grafana/provisioning/dashboards 14 | foldersFromFilesStructure: true 15 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/docker/dashboards/provisioner.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: 'default' 5 | orgId: 1 6 | folder: '' 7 | folderUid: '' 8 | type: file 9 | disableDeletion: false 10 | updateIntervalSeconds: 10 11 | allowUiUpdates: true 12 | options: 13 | path: /etc/grafana/provisioning/dashboards 14 | foldersFromFilesStructure: true 15 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/logging/ConfigurationLogging.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.logging; 3 | 4 | /** 5 | * Use this interface to log configuration data. 6 | */ 7 | public interface ConfigurationLogging { 8 | /** 9 | * Log the configuration data. 10 | */ 11 | void log(); 12 | } 13 | -------------------------------------------------------------------------------- /tools-and-tests/tools/src/main/resources/clientDefaultConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "flowControlTimeoutMillis": 15000, 3 | "initialWindowSize": 65535, 4 | "maxFrameSize": 16384, 5 | "maxHeaderListSize": -1, 6 | "pingEnabled": false, 7 | "pingTimeoutMillis": 500, 8 | "readTimeoutMillis": 10000, 9 | "priorKnowledge": false, 10 | "serverMaxMessageSizeBytes": 1048576, 11 | "delayBetweenBlocksMs": 10 12 | } 13 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.blockNode.secret }} 2 | {{- /* 3 | SPDX-License-Identifier: Apache-2.0 4 | */}} 5 | 6 | apiVersion: v1 7 | kind: Secret 8 | metadata: 9 | name: {{ include "hiero-block-node.fullname" . }}-secret 10 | type: Opaque 11 | data: 12 | {{- range $key, $value := .Values.blockNode.secret }} 13 | {{ $key }}: {{ $value | b64enc }} 14 | {{- end }} 15 | {{- end}} 16 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | SPDX-License-Identifier: Apache-2.0 3 | */}} 4 | 5 | apiVersion: v1 6 | kind: ConfigMap 7 | metadata: 8 | name: {{ include "hiero-block-node.fullname" . }}-config 9 | data: 10 | VERSION: {{ include "hiero-block-node.appVersion" . | quote }} 11 | {{- range $key, $value := .Values.blockNode.config }} 12 | {{ $key }}: {{ $value | quote }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/configmap-logging.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ include "hiero-block-node.fullname" . }}-logging-config 5 | data: 6 | logging.properties: | 7 | # Log properties 8 | .level= {{ .Values.blockNode.logs.level }} 9 | 10 | {{- range $key, $value := .Values.blockNode.logs.loggingProperties }} 11 | {{ $key }}={{ $value }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /docs/design/how-to-design-doc.md: -------------------------------------------------------------------------------- 1 | # How to start a design doc 2 | 3 | 1) Copy the [template](../../../../docs/design/design-doc-template.mdn/design-doc-template.md) from `docs/design/design-doc-template.md` to a new markdown file. 4 | 2) Take a look at [this example](../../block-node/server/docs/design/block-verification.md) `docs/design/block-verification.md` for the detail level and tone. 5 | 3) Fill out the template with your design. 6 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/BlockNodeContainerConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites; 3 | 4 | import java.util.Map; 5 | 6 | /** 7 | * Configuration for a single Block Node instance in test suites. 8 | */ 9 | public record BlockNodeContainerConfig( 10 | int port, int metricPort, String backfillSourcePath, Map envOverrides) {} 11 | -------------------------------------------------------------------------------- /block-node/verification/src/main/java/org/hiero/block/node/verification/VerificationConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.verification; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | 6 | /** 7 | * Configuration for the verification module. 8 | * Add here configuration related to TSS when needed. 9 | */ 10 | @ConfigData("verification") 11 | public record VerificationConfig() {} 12 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/types/GenerationMode.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.types; 3 | 4 | /** The GenerationMode enum defines the modes of generation for the block stream. */ 5 | public enum GenerationMode { 6 | /** Reads Blocks from a Folder. */ 7 | DIR, 8 | /** Generates Blocks from rules */ 9 | CRAFT 10 | } 11 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/blockmessaging/BlockSource.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.blockmessaging; 3 | 4 | /** 5 | * Enum representing the source of a block in the block messaging system. 6 | * This is used to differentiate the origin of the block data. 7 | */ 8 | public enum BlockSource { 9 | UNKNOWN, 10 | PUBLISHER, 11 | BACKFILL, 12 | HISTORY 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | module org.hiero.block.common { 3 | exports org.hiero.block.common.constants; 4 | exports org.hiero.block.common.utils; 5 | exports org.hiero.block.common.hasher; 6 | 7 | requires transitive com.hedera.pbj.runtime; 8 | requires transitive org.hiero.block.protobuf.pbj; 9 | requires com.swirlds.common; 10 | requires static com.github.spotbugs.annotations; 11 | } 12 | -------------------------------------------------------------------------------- /tools-and-tests/tools/docker/update-env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This scripts create a '.env' file that is used for docker & docker-compose as an input of environment variables. 4 | # This script is called by gradle and get the current project version as an input param 5 | 6 | if [ $# -lt 1 ]; then 7 | # is required! 8 | echo "USAGE: $0 " 9 | exit 1 10 | fi 11 | 12 | project_version=$1 13 | 14 | echo "VERSION=$project_version" > .env 15 | -------------------------------------------------------------------------------- /charts/block-node-server/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/blockstream-simulator/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | SPDX-License-Identifier: Apache-2.0 3 | */}} 4 | 5 | {{- if .Values.serviceAccount.create -}} 6 | apiVersion: v1 7 | kind: ServiceAccount 8 | metadata: 9 | name: {{ include "hiero-block-node.serviceAccountName" . }} 10 | labels: 11 | {{- include "hiero-block-node.labels" . | nindent 4 }} 12 | {{- with .Values.serviceAccount.annotations }} 13 | annotations: 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/config/logging/TestSecretConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.logging; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | 7 | @ConfigData("test") 8 | public record TestSecretConfig( 9 | @ConfigProperty(defaultValue = "secretValue") String secret, 10 | @ConfigProperty(defaultValue = "") String emptySecret) {} 11 | -------------------------------------------------------------------------------- /block-node/app/src/test/java/org/hiero/block/node/app/logging/TestSecretConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app.logging; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | 7 | @SuppressWarnings("unused") 8 | @ConfigData("test") 9 | public record TestSecretConfig( 10 | @ConfigProperty(defaultValue = "secretValue") String secret, 11 | @ConfigProperty(defaultValue = "") String emptySecret) {} 12 | -------------------------------------------------------------------------------- /block-node/app-config/src/test/java/org/hiero/block/node/app/config/TestSecretConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app.config; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | 7 | @SuppressWarnings("unused") 8 | @ConfigData("test") 9 | public record TestSecretConfig( 10 | @ConfigProperty(defaultValue = "secretValue") String secret, 11 | @ConfigProperty(defaultValue = "") String emptySecret) {} 12 | -------------------------------------------------------------------------------- /block-node/app/docker/metrics/datasources/datasources.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: Prometheus 5 | type: prometheus 6 | uid: prometheus 7 | access: proxy 8 | url: http://prometheus:9090 9 | isDefault: true 10 | editable: true 11 | jsonData: 12 | timeInterval: 1s 13 | 14 | - name: Loki 15 | type: loki 16 | access: proxy 17 | orgId: 1 18 | url: http://loki:3100 19 | basicAuth: false 20 | isDefault: false 21 | version: 1 22 | editable: true 23 | -------------------------------------------------------------------------------- /charts/block-node-server/values-overrides/mid-size.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | requests: 3 | cpu: "8" 4 | memory: "12Gi" 5 | 6 | blockNode: 7 | config: 8 | JAVA_OPTS: '-Xms8G -Xmx8G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="/tmp/dump.hprof"' 9 | MESSAGING_BLOCK_ITEM_QUEUE_SIZE: "1024" 10 | MESSAGING_BLOCK_NOTIFICATION_QUEUE_SIZE: "64" 11 | BACKFILL_FETCH_BATCH_SIZE: "20" 12 | persistence: 13 | archive: 14 | size: 16Gi 15 | live: 16 | size: 4Gi 17 | logging: 18 | size: 2Gi 19 | -------------------------------------------------------------------------------- /tools-and-tests/tools/src/main/resources/serverDefaultConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "initialWindowSize": 8388608, 3 | "maxFrameSize": 524288, 4 | "maxHeaderListSize": 8192, 5 | "maxConcurrentStreams": 8, 6 | "flowControlTimeoutMillis": 250, 7 | "sendBufferSize": 131072, 8 | "receiveBufferSize": 131072, 9 | "maxMessageSizeBytes": 16777215, 10 | "tcpNoDelay": true, 11 | "maxEmptyFrames": 10, 12 | "maxRapidResets": 50, 13 | "rapidResetTimeWindowMillis": 10000, 14 | "backlogSize": 8192, 15 | "writeQueueLength": 8192 16 | } 17 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/docker/datasources.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: Prometheus 5 | type: prometheus 6 | uid: prometheus 7 | access: proxy 8 | url: http://prometheus-simulator:9091 9 | isDefault: true 10 | editable: true 11 | jsonData: 12 | timeInterval: 1s 13 | 14 | - name: Loki 15 | type: loki 16 | access: proxy 17 | orgId: 1 18 | url: http://loki-simulator:3100 19 | basicAuth: false 20 | isDefault: false 21 | version: 1 22 | editable: true 23 | -------------------------------------------------------------------------------- /block-node/backfill/src/main/java/org/hiero/block/node/backfill/client/proto/block_node_source.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | syntax = "proto3"; 3 | 4 | package org.hiero.block.node.backfill.client; 5 | 6 | message BackfillSource { 7 | repeated BackfillSourceConfig nodes = 1; // Array of BlockNode messages 8 | } 9 | 10 | message BackfillSourceConfig { 11 | string address = 1; // Address as a string (either hostname or IP) 12 | uint32 port = 2; // Port number 13 | uint32 priority = 3; // Priority for each node 14 | } 15 | -------------------------------------------------------------------------------- /block-node/health/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.health.HealthServicePlugin; 3 | 4 | // SPDX-License-Identifier: Apache-2.0 5 | module org.hiero.block.node.health { 6 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 7 | 8 | requires transitive org.hiero.block.node.spi; 9 | requires transitive io.helidon.webserver; 10 | requires com.github.spotbugs.annotations; 11 | 12 | provides org.hiero.block.node.spi.BlockNodePlugin with 13 | HealthServicePlugin; 14 | } 15 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/logging/Loggable.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.logging; 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * This annotation is used to mark record components that should be logged. 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target({ElementType.RECORD_COMPONENT}) 14 | public @interface Loggable {} 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | version: 2 3 | updates: 4 | - package-ecosystem: github-actions 5 | directory: / 6 | schedule: 7 | interval: daily 8 | open-pull-requests-limit: 10 9 | 10 | - package-ecosystem: docker 11 | directory: /auth-layer-proxy 12 | schedule: 13 | interval: daily 14 | 15 | - package-ecosystem: gradle 16 | directory: /hiero-dependency-versions 17 | schedule: 18 | interval: weekly 19 | 20 | - package-ecosystem: gradle 21 | directory: / 22 | schedule: 23 | interval: weekly 24 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/testFixtures/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | module org.hiero.block.simulator.test.fixtures { 3 | exports org.hiero.block.simulator.fixtures; 4 | exports org.hiero.block.simulator.fixtures.blocks; 5 | exports org.hiero.block.simulator.fixtures.generator; 6 | 7 | requires com.swirlds.common; 8 | requires com.swirlds.config.extensions; 9 | requires org.hiero.block.protobuf.protoc; 10 | requires org.hiero.block.simulator; 11 | requires com.google.protobuf; 12 | requires org.junit.jupiter.api; 13 | } 14 | -------------------------------------------------------------------------------- /block-node/block-access-service/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.access.service.BlockAccessServicePlugin; 3 | 4 | module org.hiero.block.node.access.service { 5 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 6 | 7 | requires transitive org.hiero.block.node.spi; 8 | requires transitive org.hiero.block.protobuf.pbj; 9 | requires com.hedera.pbj.runtime; 10 | requires com.swirlds.metrics.api; 11 | 12 | provides org.hiero.block.node.spi.BlockNodePlugin with 13 | BlockAccessServicePlugin; 14 | } 15 | -------------------------------------------------------------------------------- /charts/blockstream-simulator/Chart.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | apiVersion: v2 3 | appVersion: 0.26.0-SNAPSHOT 4 | description: A Helm chart for Hiero Blockstream Simulator. 5 | home: https://github.com/hiero-ledger/hiero-block-node 6 | keywords: 7 | - blocknode 8 | - dlt 9 | - hiero 10 | - hedera 11 | - hashgraph 12 | - blockstream 13 | - simulator 14 | maintainers: 15 | - name: Hiero Block Node Team 16 | email: blocknode@hashgraph.com 17 | name: blockstream-simulator-chart 18 | sources: 19 | - https://github.com/hiero-ledger/hiero-block-node 20 | version: 0.26.0-SNAPSHOT 21 | -------------------------------------------------------------------------------- /tool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: Apache-2.0 3 | # run gradle jar build and send output to /dev/null 4 | ./gradlew -q tool:shadowJar > /dev/null 5 | # check if last command failed and exit if so 6 | if [ $? -ne 0 ]; then 7 | echo "Build failed" 8 | exit 1 9 | fi 10 | # change to the tools directory 11 | pushd tools > /dev/null 12 | # find the jar name in the build/libs directory 13 | JAR=$(find build/libs -name 'tools-*-all.jar') 14 | # run the command line tool built jar file forwarding all arguments 15 | java -jar $JAR "$@" 16 | # change back to the original directory 17 | popd > /dev/null 18 | -------------------------------------------------------------------------------- /tools-and-tests/tools/src/main/java/org/hiero/block/tools/commands/record2blocks/model/ChainFileAndCount.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.tools.commands.record2blocks.model; 3 | 4 | /** 5 | * Simple Record for a ChainFile and the count of how many times there are similar chain files for a record file set. 6 | * 7 | * @param chainFile A chain file that is one of the common identical ones in a record file set 8 | * @param count The number of files that are identical in the record file set 9 | */ 10 | public record ChainFileAndCount(ChainFile chainFile, int count) {} 11 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/config/types/GenerationModeTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.types; 3 | 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | class GenerationModeTest { 9 | 10 | @Test 11 | void testGenerationMode() { 12 | GenerationMode mode = GenerationMode.DIR; 13 | assertEquals(GenerationMode.DIR, mode); 14 | mode = GenerationMode.CRAFT; 15 | assertEquals(GenerationMode.CRAFT, mode); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /block-node/app-config/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node Server App Configuration" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { runtimeOnly("com.swirlds.config.impl") } 11 | 12 | testModuleInfo { 13 | requires("org.junit.jupiter.api") 14 | exportsTo("com.swirlds.config.impl") 15 | } 16 | -------------------------------------------------------------------------------- /block-node/app/docker/docker-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ $# -lt 1 ]]; then 4 | echo "Usage: ${0} [version] [project_dir]" 5 | exit 1 6 | fi 7 | 8 | VERSION=$1 9 | 10 | echo "Building image [block-node-server:${VERSION}]" 11 | echo 12 | 13 | SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) 14 | # run docker build 15 | docker buildx build --load -t "block-node-server:${VERSION}" \ 16 | --build-context distributions=../distributions \ 17 | --build-arg VERSION="${VERSION}" \ 18 | --build-arg SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH}" . || exit "${?}" 19 | 20 | echo 21 | echo "Image [block-node-server:${VERSION}] built successfully!" 22 | -------------------------------------------------------------------------------- /block-node/server-status/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.server.status.ServerStatusServicePlugin; 3 | 4 | module org.hiero.block.node.server.status { 5 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 6 | 7 | requires transitive org.hiero.block.node.spi; 8 | requires transitive org.hiero.block.protobuf.pbj; 9 | requires com.hedera.pbj.runtime; 10 | requires com.swirlds.metrics.api; 11 | requires com.github.spotbugs.annotations; 12 | 13 | provides org.hiero.block.node.spi.BlockNodePlugin with 14 | ServerStatusServicePlugin; 15 | } 16 | -------------------------------------------------------------------------------- /tools-and-tests/k6/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k6", 3 | "version": "0.0.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "k6", 9 | "version": "0.0.1", 10 | "devDependencies": { 11 | "@types/k6": "^1.4.0" 12 | } 13 | }, 14 | "node_modules/@types/k6": { 15 | "version": "1.4.0", 16 | "resolved": "https://registry.npmjs.org/@types/k6/-/k6-1.4.0.tgz", 17 | "integrity": "sha512-2tgKVnzNXZTZT1TDAGLY/3cuvHPZLyOF751N7M8T2dBgWzInzUVZYjGn9zVW01S1yNLqAr1az9gctyJHTW6GRQ==", 18 | "dev": true, 19 | "license": "MIT" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /charts/blockstream-simulator/templates/pvc-simulator-data.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.simulator.persistence.data.create }} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: {{ include "blockstream-simulator-chart.fullname" . }}-data 6 | labels: 7 | {{- include "blockstream-simulator-chart.labels" . | nindent 4 }} 8 | spec: 9 | accessModes: 10 | - ReadWriteOnce 11 | resources: 12 | requests: 13 | storage: {{ .Values.simulator.persistence.data.size }} 14 | {{- if .Values.simulator.persistence.data.storageClass }} 15 | storageClassName: {{ .Values.simulator.persistence.data.storageClass }} 16 | {{- end }} 17 | {{- end }} 18 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/metrics/MetricsService.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.metrics; 3 | 4 | import com.swirlds.metrics.api.Counter; 5 | import edu.umd.cs.findbugs.annotations.NonNull; 6 | 7 | /** Use member variables of this class to update metric data for the Hedera Block Node. */ 8 | public interface MetricsService { 9 | /** 10 | * Use this method to get a specific counter for the given metric type. 11 | * 12 | * @param key to get a specific counter 13 | * @return the counter 14 | */ 15 | Counter get(@NonNull SimulatorMetricTypes.Counter key); 16 | } 17 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/block/access/BlockAccessTestSuites.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites.block.access; 3 | 4 | import org.junit.platform.suite.api.SelectClasses; 5 | import org.junit.platform.suite.api.Suite; 6 | 7 | /** 8 | * Test suite for running block access tests, including both positive and negative test 9 | * scenarios. 10 | * 11 | *

This suite aggregates the tests from {@link GetBlockApiTests}. The {@code @Suite} 12 | * annotation allows running all selected classes in a single test run. 13 | */ 14 | @Suite 15 | @SelectClasses({GetBlockApiTests.class}) 16 | public class BlockAccessTestSuites {} 17 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/metrics/MetricsTestSuites.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites.metrics; 3 | 4 | import org.junit.platform.suite.api.SelectClasses; 5 | import org.junit.platform.suite.api.Suite; 6 | 7 | /** 8 | * Test suite for running metrics-related tests. 9 | * 10 | *

This suite aggregates the tests from {@link MetricsCommonTests}. The {@code @Suite} 11 | * annotation allows running all selected classes in a single test run. 12 | */ 13 | @Suite 14 | @SelectClasses({ 15 | MetricsCommonTests.class, 16 | // Add other metrics test classes here as needed 17 | }) 18 | public class MetricsTestSuites {} 19 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/configmap-block-node-sources.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (and .Values.blockNode.backfill .Values.blockNode.backfill.sources) (gt (len .Values.blockNode.backfill.sources) 0) }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ include "hiero-block-node.fullname" . }}-block-node-sources 6 | data: 7 | {{ .Values.blockNode.backfill.filename }}: | 8 | { 9 | "nodes": [ 10 | {{- range $index, $node := .Values.blockNode.backfill.sources }} 11 | {{- if $index }},{{ end }} 12 | { "address": "{{ $node.address }}", "port": {{ $node.port }}, "priority": {{ $node.priority }} } 13 | {{- end }} 14 | ] 15 | } 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Commons module with logic that could be abstracted and reused." 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | testModuleInfo { 11 | requiresStatic("com.github.spotbugs.annotations") 12 | requires("org.junit.jupiter.api") 13 | requires("org.junit.jupiter.params") 14 | requires("org.assertj.core") 15 | requires("com.google.common.jimfs") 16 | } 17 | -------------------------------------------------------------------------------- /block-node/base/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | module org.hiero.block.node.base { 3 | exports org.hiero.block.node.base; 4 | exports org.hiero.block.node.base.ranges; 5 | exports org.hiero.block.node.base.s3; 6 | exports org.hiero.block.node.base.tar; 7 | 8 | requires transitive org.hiero.block.node.spi; 9 | requires com.hedera.pbj.runtime; 10 | requires org.hiero.block.common; 11 | requires com.github.luben.zstd_jni; 12 | requires java.net.http; 13 | requires java.xml; 14 | requires static transitive com.github.spotbugs.annotations; 15 | requires static java.compiler; // javax.annotation.processing.Generated 16 | } 17 | -------------------------------------------------------------------------------- /block-node/base/src/main/java/org/hiero/block/node/base/s3/S3ClientException.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.base.s3; 3 | 4 | /** 5 | * A checked exception to act as a base for all S3 client exceptions. 6 | */ 7 | public class S3ClientException extends Exception { 8 | public S3ClientException() { 9 | super(); 10 | } 11 | 12 | public S3ClientException(final String message) { 13 | super(message); 14 | } 15 | 16 | public S3ClientException(final Throwable cause) { 17 | super(cause); 18 | } 19 | 20 | public S3ClientException(final String message, final Throwable cause) { 21 | super(message, cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /block-node/base/src/main/java/org/hiero/block/node/base/s3/S3ClientInitializationException.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.base.s3; 3 | 4 | public class S3ClientInitializationException extends S3ClientException { 5 | public S3ClientInitializationException() { 6 | super(); 7 | } 8 | 9 | public S3ClientInitializationException(final String message) { 10 | super(message); 11 | } 12 | 13 | public S3ClientInitializationException(final Throwable cause) { 14 | super(cause); 15 | } 16 | 17 | public S3ClientInitializationException(final String message, final Throwable cause) { 18 | super(message, cause); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/types/SimulatorMode.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.types; 3 | 4 | /** The SimulatorMode enum defines the work modes of the block stream simulator. */ 5 | public enum SimulatorMode { 6 | /** 7 | * Indicates a work mode in which the simulator is working in consumer mode. 8 | */ 9 | CONSUMER, 10 | /** 11 | * Indicates a work mode in which the simulator is working as both consumer and publisher. 12 | */ 13 | PUBLISHER_SERVER, 14 | /** 15 | * Indicates a work mode in which the simulator is working in publisher mode. 16 | */ 17 | PUBLISHER_CLIENT 18 | } 19 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/server/status/ServerStatusTestSuites.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites.server.status; 3 | 4 | import org.hiero.block.suites.server.status.positive.PositiveServerStatusTests; 5 | import org.junit.platform.suite.api.SelectClasses; 6 | import org.junit.platform.suite.api.Suite; 7 | 8 | @Suite 9 | @SelectClasses({PositiveServerStatusTests.class}) 10 | public class ServerStatusTestSuites { 11 | /** 12 | * Default constructor for the {@link ServerStatusTestSuites} class.This constructor is 13 | * empty as it does not need to perform any initialization. 14 | */ 15 | public ServerStatusTestSuites() {} 16 | } 17 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/verification/BlockVerificationTestSuites.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites.verification; 3 | 4 | import org.junit.platform.suite.api.SelectClasses; 5 | import org.junit.platform.suite.api.Suite; 6 | 7 | /** 8 | * Test suite for running block verification tests, including both positive and negative test 9 | * scenarios. 10 | * 11 | *

This suite aggregates the tests from {@link VerificationCommonTests}. The {@code @Suite} 12 | * annotation allows running all selected classes in a single test run. 13 | */ 14 | @Suite 15 | @SelectClasses({VerificationCommonTests.class}) 16 | public class BlockVerificationTestSuites {} 17 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | SPDX-License-Identifier: Apache-2.0 3 | */}} 4 | 5 | {{ if .Values.kubepromstack.enabled }} 6 | apiVersion: monitoring.coreos.com/v1 7 | kind: ServiceMonitor 8 | metadata: 9 | name: {{ include "hiero-block-node.fullname" . }} 10 | labels: 11 | app: {{ include "hiero-block-node.name" . }} 12 | release: {{ .Release.Name }} 13 | {{- include "hiero-block-node.labels" . | nindent 4 }} 14 | spec: 15 | selector: 16 | matchLabels: 17 | app: {{ include "hiero-block-node.name" . }} 18 | namespaceSelector: 19 | matchNames: 20 | - {{ .Release.Namespace }} 21 | endpoints: 22 | - port: metrics 23 | interval: 15s 24 | 25 | {{- end }} 26 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/docker/simulator-prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 1s 3 | 4 | scrape_configs: 5 | - job_name: 'simulator-publisher' 6 | static_configs: 7 | - targets: ['simulator-publisher:16008'] 8 | metrics_path: '/metrics' 9 | scheme: 'http' 10 | relabel_configs: 11 | - source_labels: [__name__] 12 | target_label: instance_type 13 | replacement: 'publisher' 14 | 15 | - job_name: 'simulator-consumer' 16 | static_configs: 17 | - targets: ['simulator-consumer:16009'] 18 | metrics_path: '/metrics' 19 | scheme: 'http' 20 | relabel_configs: 21 | - source_labels: [__name__] 22 | target_label: instance_type 23 | replacement: 'consumer' 24 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/config/types/StreamingModeTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.types; 3 | 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | import static org.junit.jupiter.api.Assertions.assertThrows; 6 | 7 | class StreamingModeTest { 8 | 9 | @org.junit.jupiter.api.Test 10 | void fromString() { 11 | assertEquals(StreamingMode.CONSTANT_RATE, StreamingMode.fromString("CONSTANT_RATE")); 12 | assertEquals(StreamingMode.MILLIS_PER_BLOCK, StreamingMode.fromString("MILLIS_PER_BLOCK")); 13 | assertThrows(IllegalArgumentException.class, () -> StreamingMode.fromString("INVALID")); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tools-and-tests/tools/docker/docker-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ $# -lt 1 ]]; then 4 | echo "Usage: ${0} [version] [arch (amd64|arm64)]" 5 | exit 1 6 | fi 7 | 8 | VERSION=$1 9 | ARCH=$2 10 | [[ -n "$ARCH" ]] && PLATFORM_ARG="--platform linux/${ARCH}" 11 | 12 | echo "Building image [block-tools:${VERSION}]" 13 | echo 14 | 15 | SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) 16 | # run docker build 17 | docker buildx build --load -t "block-tools:${VERSION}" \ 18 | ${PLATFORM_ARG} \ 19 | --build-context distributions=../distributions \ 20 | --build-arg VERSION="${VERSION}" \ 21 | --build-arg SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH}" . || exit "${?}" 22 | 23 | echo 24 | echo "Image [block-tools:${VERSION}] built successfully!" 25 | -------------------------------------------------------------------------------- /block-node/server-status/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node - Block Node Server Status API Module" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("io.helidon.logging.jul") 13 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 14 | } 15 | 16 | testModuleInfo { 17 | requires("org.junit.jupiter.api") 18 | requires("org.hiero.block.node.app.test.fixtures") 19 | } 20 | -------------------------------------------------------------------------------- /block-node/block-access-service/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node - Block Access Service API Module" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("io.helidon.logging.jul") 13 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 14 | } 15 | 16 | testModuleInfo { 17 | requires("org.junit.jupiter.api") 18 | requires("org.hiero.block.node.app.test.fixtures") 19 | } 20 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/Constants.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator; 3 | 4 | /** The Constants class defines the constants for the block simulator. */ 5 | public final class Constants { 6 | /** The file extension for block files. */ 7 | public static final String RECORD_EXTENSION = ".blk"; 8 | 9 | /** postfix for gzip files */ 10 | public static final String GZ_EXTENSION = ".gz"; 11 | 12 | /** 13 | * Used for converting nanoseconds to milliseconds and vice versa 14 | */ 15 | public static final int NANOS_PER_MILLI = 1_000_000; 16 | 17 | /** Constructor to prevent instantiation. this is only a utility class */ 18 | private Constants() {} 19 | } 20 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | max_report_age: off 3 | 4 | # Only comment on PRs initially and when coverage changes 5 | comment: 6 | layout: "diff, flags, files" 7 | behavior: new # deletes old comment and posts a new one 8 | require_changes: true 9 | 10 | coverage: 11 | status: 12 | patch: 13 | default: 14 | target: 80% 15 | threshold: 1% 16 | only_pulls: true 17 | project: 18 | default: 19 | target: 80% 20 | threshold: 1% 21 | branches: 22 | - main 23 | 24 | ignore: 25 | - "simulator/src/main/java/org/hiero/block/simulator/BlockStreamSimulator.java" 26 | - "tools-and-tests/tools/**" 27 | - "tools-and-tests/suites/**" 28 | - "**/src/test/**" 29 | - "block-node/app/src/testFixtures/**" 30 | -------------------------------------------------------------------------------- /charts/block-node-server/values-overrides/backfill.yaml: -------------------------------------------------------------------------------- 1 | blockNode: 2 | config: 3 | BACKFILL_BLOCK_NODE_SOURCES_PATH: "/opt/hiero/block-node/backfill/block-node-sources.json" 4 | BACKFILL_FETCH_BATCH_SIZE: "10" 5 | backfill: 6 | # The path to the block-node-sources.json file must match the path property in 7 | # blockNode.config.BACKFILL_BLOCK_NODE_SOURCES_PATH 8 | path: "/opt/hiero/block-node/backfill" 9 | filename: "block-node-sources.json" 10 | sources: 11 | # note that this is an example of another (source) BN on the same K8 cluster 12 | # different namespace ..svc.cluster.local 13 | - address: "source-block-node-helm-chart.source.svc.cluster.local" 14 | port: 40840 15 | priority: 1 16 | -------------------------------------------------------------------------------- /protobuf-sources/src/main/proto/block-node/api/reconnect_service.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | syntax = "proto3"; 3 | 4 | package org.hiero.block.api; 5 | 6 | option java_package = "org.hiero.block.api.protoc"; 7 | // <<>> This comment is special code for setting PBJ Compiler java package 8 | option java_multiple_files = true; 9 | 10 | message ReconnectRequest {} 11 | 12 | message ReconnectResponse {} 13 | 14 | /** 15 | * Remote procedure calls (RPCs) for the Block Node reconnect services. 16 | */ 17 | service ReconnectService { 18 | /** 19 | * Request reconnect data comprised of state and block data from the block node. 20 | */ 21 | rpc reconnect(ReconnectRequest) returns (stream ReconnectResponse); 22 | } 23 | -------------------------------------------------------------------------------- /block-node/health/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node Health Service" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("org.apache.logging.log4j.slf4j2.impl") 13 | runtimeOnly("io.helidon.logging.jul") 14 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 15 | } 16 | 17 | testModuleInfo { 18 | requires("org.junit.jupiter.api") 19 | requires("org.mockito") 20 | requires("org.mockito.junit.jupiter") 21 | } 22 | -------------------------------------------------------------------------------- /block-node/stream-publisher/src/main/java/org/hiero/block/node/stream/publisher/PublisherConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.stream.publisher; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | import com.swirlds.config.api.validation.annotation.Min; 7 | import org.hiero.block.node.base.Loggable; 8 | 9 | /** 10 | * Configuration for a block stream publisher plugin. 11 | */ 12 | @ConfigData("producer") 13 | public record PublisherConfig( 14 | @Loggable @ConfigProperty(defaultValue = "9_223_372_036_854_775_807") @Min(100_000L) long batchForwardLimit) { 15 | // Do not create a constructor just to validate the `@Min`, because that's 16 | // already done in the Configuration framework initialization. 17 | } 18 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/StartupDataInjectionModule.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.startup; 3 | 4 | import dagger.Binds; 5 | import dagger.Module; 6 | import javax.inject.Singleton; 7 | import org.hiero.block.simulator.startup.impl.SimulatorStartupDataImpl; 8 | 9 | /** 10 | * Injection module for the startup data. 11 | */ 12 | @Module 13 | public interface StartupDataInjectionModule { 14 | /** 15 | * @param impl the implementation of the startup data 16 | * 17 | * @return valid, non-null, fully initialized singleton instance of the 18 | * startup data 19 | */ 20 | @Singleton 21 | @Binds 22 | SimulatorStartupData bindSimulatorStartupData(final SimulatorStartupDataImpl impl); 23 | } 24 | -------------------------------------------------------------------------------- /block-node/spi-plugins/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node Plugin SPI" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("org.apache.logging.log4j.slf4j2.impl") 13 | runtimeOnly("io.helidon.logging.jul") 14 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 15 | } 16 | 17 | testModuleInfo { 18 | requires("org.junit.jupiter.api") 19 | requires("org.junit.jupiter.params") 20 | requires("com.github.luben.zstd_jni") 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/org/hiero/block/common/constants/StringsConstants.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.common.constants; 3 | 4 | /** A class that hold common String literals used across projects. */ 5 | public final class StringsConstants { 6 | /** 7 | * File name for application properties 8 | */ 9 | public static final String APPLICATION_PROPERTIES = "app.properties"; 10 | 11 | /** 12 | * File name for application test properties (may override APPLICATION_PROPERTIES) 13 | */ 14 | public static final String APPLICATION_TEST_PROPERTIES = "app-test.properties"; 15 | 16 | /** 17 | * File name for logging properties 18 | */ 19 | public static final String LOGGING_PROPERTIES = "logging.properties"; 20 | 21 | private StringsConstants() {} 22 | } 23 | -------------------------------------------------------------------------------- /block-node/app/src/main/resources/app.properties: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | prometheus.endpointPortNumber=16007 4 | server.port=40840 5 | 6 | # Ring buffer sizes for the mediator and notifier 7 | # with default values. 8 | #mediator.ringBufferSize=4096 9 | #notifier.ringBufferSize=1024 10 | 11 | # Timeout for consumers to wait for block item before timing out. 12 | # Default is 1500 milliseconds. 13 | #consumer.timeoutThresholdMillis=1500 14 | 15 | #Persistence Storage Config 16 | #persistence.storage.liveRootPath= 17 | #persistence.storage.archiveRootPath= 18 | #persistence.storage.type=BLOCK_AS_LOCAL_FILE 19 | #persistence.storage.compression=ZSTD 20 | #persistence.storage.archiveGroupSize=1_000 21 | #backfill.blockNodeSourcesPath=/Users/user/Projects/hiero-block-node/block-node/backfill/src/test/resources/block-nodes.json 22 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/service.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | SPDX-License-Identifier: Apache-2.0 3 | */}} 4 | 5 | apiVersion: v1 6 | kind: Service 7 | metadata: 8 | name: {{ include "hiero-block-node.fullname" . }} 9 | labels: 10 | app: {{ include "hiero-block-node.name" . }} 11 | {{- include "hiero-block-node.labels" . | nindent 4 }} 12 | {{- with .Values.service.annotations }} 13 | annotations: 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | spec: 17 | type: {{ .Values.service.type }} 18 | ports: 19 | - port: {{ .Values.service.port }} 20 | targetPort: http 21 | protocol: TCP 22 | name: http 23 | - name: metrics 24 | port: {{ .Values.blockNode.health.metrics.port }} 25 | targetPort: metrics 26 | selector: 27 | {{- include "hiero-block-node.selectorLabels" . | nindent 4 }} 28 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/utils/ServerStatusUtils.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites.utils; 3 | 4 | import edu.umd.cs.findbugs.annotations.NonNull; 5 | import org.hiero.block.api.protoc.BlockNodeServiceGrpc; 6 | import org.hiero.block.api.protoc.ServerStatusRequest; 7 | import org.hiero.block.api.protoc.ServerStatusResponse; 8 | 9 | public final class ServerStatusUtils { 10 | private ServerStatusUtils() { 11 | // Prevent instantiation 12 | } 13 | 14 | public static ServerStatusResponse requestServerStatus( 15 | @NonNull final BlockNodeServiceGrpc.BlockNodeServiceBlockingStub blockNodeServiceStub) { 16 | return blockNodeServiceStub.serverStatus( 17 | ServerStatusRequest.newBuilder().build()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /block-node/app/docker/loki-config.yaml: -------------------------------------------------------------------------------- 1 | auth_enabled: false 2 | server: 3 | http_listen_port: 3100 4 | grpc_listen_port: 9096 5 | common: 6 | instance_addr: 127.0.0.1 7 | path_prefix: /tmp/loki 8 | storage: 9 | filesystem: 10 | chunks_directory: /tmp/loki/chunks 11 | rules_directory: /tmp/loki/rules 12 | replication_factor: 1 13 | ring: 14 | kvstore: 15 | store: inmemory 16 | query_range: 17 | results_cache: 18 | cache: 19 | embedded_cache: 20 | enabled: true 21 | max_size_mb: 100 22 | schema_config: 23 | configs: 24 | - from: 2020-10-24 25 | store: tsdb 26 | object_store: filesystem 27 | schema: v13 28 | index: 29 | prefix: index_ 30 | period: 24h 31 | ruler: 32 | alertmanager_url: http://localhost:9093 33 | analytics: 34 | reporting_enabled: false 35 | -------------------------------------------------------------------------------- /block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/plugintest/NoBlocksHistoricalBlockFacility.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app.fixtures.plugintest; 3 | 4 | import org.hiero.block.node.spi.historicalblocks.BlockAccessor; 5 | import org.hiero.block.node.spi.historicalblocks.BlockRangeSet; 6 | import org.hiero.block.node.spi.historicalblocks.HistoricalBlockFacility; 7 | 8 | /** 9 | * A {@link HistoricalBlockFacility} that does not provide any blocks, for testing. 10 | */ 11 | public class NoBlocksHistoricalBlockFacility implements HistoricalBlockFacility { 12 | @Override 13 | public BlockAccessor block(long blockNumber) { 14 | return null; 15 | } 16 | 17 | @Override 18 | public BlockRangeSet availableBlocks() { 19 | return BlockRangeSet.EMPTY; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/org/hiero/block/common/hasher/Hashes.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.common.hasher; 3 | 4 | import edu.umd.cs.findbugs.annotations.NonNull; 5 | import java.nio.ByteBuffer; 6 | 7 | /** 8 | * Holds the input and output hashes of a list of block items. 9 | * 10 | * @param inputHashes the input hashes 11 | * @param outputHashes the output hashes 12 | * @param consensusHeaderHashes the consensus header hashes 13 | * @param stateChangesHashes the state changes hashes 14 | * @param traceDataHashes the trace data hashes 15 | */ 16 | public record Hashes( 17 | @NonNull ByteBuffer inputHashes, 18 | @NonNull ByteBuffer outputHashes, 19 | @NonNull ByteBuffer consensusHeaderHashes, 20 | @NonNull ByteBuffer stateChangesHashes, 21 | @NonNull ByteBuffer traceDataHashes) {} 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/01-Story-Template.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | name: Agile Task or Feature 3 | description: Create a new task or feature 4 | projects: 5 | - "hiero-ledger/9" 6 | type: feature 7 | body: 8 | - type: textarea 9 | id: Story-Form 10 | attributes: 11 | label: Story Form 12 | description: | 13 | As a "Persona" 14 | I want to "Request" 15 | So that "Goal" 16 | value: | 17 | As a ? 18 | I want to ? 19 | So that ? 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: technical-notes 24 | attributes: 25 | label: Technical Notes 26 | description: Add any additional detail to describe this story. 27 | placeholder: | 28 | Technical details, notes, suggestions, etc... 29 | validations: 30 | required: true 31 | -------------------------------------------------------------------------------- /block-node/base/src/main/java/org/hiero/block/node/base/Loggable.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.base; 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Annotation to mark a configuration field as loggable. So that its value will be logged on server startup. Any 11 | * property without this annotation will still be logged but with its value masked. This is internationally this way 12 | * round so the default is for a property to be considered sensitive and have its value masked. With the aim to avoid 13 | * accidentally logging sensitive information. 14 | */ 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target({ElementType.RECORD_COMPONENT}) 17 | public @interface Loggable {} 18 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. **Get the application URL** by running the following commands: 2 | 3 | ```bash 4 | kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{.Release.Name}}-{{.Chart.Name}} {{ .Values.service.port }}:{{ .Values.service.port }} 5 | echo "Visit http://127.0.0.1:{{ .Values.service.port }} to use your application" 6 | ``` 7 | 8 | {{- if .Values.kubepromstack.enabled }} 9 | 10 | 11 | 2. **Access Grafana** by mapping the service port: 12 | 13 | ```bash 14 | kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{.Release.Name}}-grafana 3000:80 15 | echo "Grafana is accessible at http://localhost:3000" 16 | ``` 17 | 18 | **Note**: This command forwards your local port `3000` to Grafana's port `80`. Ensure that port `3000` is free on your local machine or choose another available port if necessary. 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/docker/loki-config.yaml: -------------------------------------------------------------------------------- 1 | auth_enabled: false 2 | server: 3 | http_listen_port: 4100 4 | grpc_listen_port: 9097 5 | common: 6 | instance_addr: 127.0.0.2 7 | path_prefix: /tmp/loki 8 | storage: 9 | filesystem: 10 | chunks_directory: /tmp/loki/chunks 11 | rules_directory: /tmp/loki/rules 12 | replication_factor: 1 13 | ring: 14 | kvstore: 15 | store: inmemory 16 | query_range: 17 | results_cache: 18 | cache: 19 | embedded_cache: 20 | enabled: true 21 | max_size_mb: 100 22 | schema_config: 23 | configs: 24 | - from: 2020-10-24 25 | store: tsdb 26 | object_store: filesystem 27 | schema: v13 28 | index: 29 | prefix: index_ 30 | period: 24h 31 | ruler: 32 | alertmanager_url: http://localhost:9094 33 | analytics: 34 | reporting_enabled: false 35 | -------------------------------------------------------------------------------- /block-node/app-config/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | module org.hiero.block.node.app.config { 3 | // export configuration classes to the config module 4 | exports org.hiero.block.node.app.config to 5 | com.swirlds.config.impl, 6 | com.swirlds.config.extensions, 7 | org.hiero.block.node.app, 8 | org.hiero.block.node.app.test.fixtures, 9 | org.hiero.block.node.stream.publisher; 10 | // export the node-wide configuration to everything. 11 | exports org.hiero.block.node.app.config.node; 12 | 13 | requires transitive com.swirlds.config.api; 14 | requires com.swirlds.base; 15 | requires org.hiero.block.node.base; 16 | requires java.logging; 17 | requires static transitive com.github.spotbugs.annotations; 18 | requires static java.compiler; 19 | } 20 | -------------------------------------------------------------------------------- /block-node/s3-archive/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node - S3 Archive Plugin" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("org.apache.logging.log4j.slf4j2.impl") 13 | runtimeOnly("io.helidon.logging.jul") 14 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 15 | } 16 | 17 | testModuleInfo { 18 | requires("org.junit.jupiter.api") 19 | requires("org.hiero.block.node.app.test.fixtures") 20 | requires("org.testcontainers") 21 | requires("io.minio") 22 | } 23 | -------------------------------------------------------------------------------- /tools-and-tests/tools/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use Eclipse Temurin with Java 25 as the base image 2 | FROM eclipse-temurin:25 3 | 4 | # Define version 5 | ARG VERSION 6 | ENV VERSION=${VERSION} 7 | 8 | # Set the working directory inside the container 9 | WORKDIR /app 10 | 11 | # Copy Distribution TAR file 12 | COPY --from=distributions tools-${VERSION}.tar . 13 | 14 | # Extract the TAR file 15 | RUN tar -xvf tools-${VERSION}.tar 16 | 17 | # Make a stable symlink so we don’t need ${VERSION} at runtime 18 | RUN ln -s /app/tools-${VERSION} /app/tools 19 | 20 | # Expose the port that the application will run on 21 | EXPOSE 8090 22 | 23 | # Exec form: argv[0] is the binary; CMD will be appended 24 | ENTRYPOINT ["/app/tools/bin/tools"] 25 | # Default args; compose can override if needed 26 | CMD ["networkCapacity","-m","server","-c","/app/conf/serverDefaultConfig.json","-p","8090"] 27 | -------------------------------------------------------------------------------- /block-node/verification/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node Verification Service" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("org.apache.logging.log4j.slf4j2.impl") 13 | runtimeOnly("io.helidon.logging.jul") 14 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 15 | } 16 | 17 | testModuleInfo { 18 | requires("org.junit.jupiter.api") 19 | requires("org.hiero.block.node.app.test.fixtures") 20 | requires("org.mockito") 21 | requires("org.junit.jupiter.params") 22 | } 23 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/metrics/MetricsInjectionModuleTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.metrics; 3 | 4 | import static org.junit.jupiter.api.Assertions.assertNotNull; 5 | 6 | import com.swirlds.config.api.Configuration; 7 | import com.swirlds.metrics.api.Metrics; 8 | import java.io.IOException; 9 | import org.hiero.block.simulator.fixtures.TestUtils; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class MetricsInjectionModuleTest { 13 | 14 | @Test 15 | void testProvideMetrics() throws IOException { 16 | Configuration configuration = TestUtils.getTestConfiguration(); 17 | 18 | // Call the method under test 19 | Metrics providedMetrics = MetricsInjectionModule.provideMetrics(configuration); 20 | 21 | assertNotNull(providedMetrics); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /block-node/stream-subscriber/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node Subscriber Service" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("org.apache.logging.log4j.slf4j2.impl") 13 | runtimeOnly("io.helidon.logging.jul") 14 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 15 | } 16 | 17 | testModuleInfo { 18 | requires("org.junit.jupiter.api") 19 | requires("org.junit.jupiter.params") 20 | requires("org.hiero.block.node.app.test.fixtures") 21 | requires("org.assertj.core") 22 | } 23 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/data/GrpcConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.data; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | import com.swirlds.config.api.validation.annotation.Max; 7 | import com.swirlds.config.api.validation.annotation.Min; 8 | import org.hiero.block.simulator.config.logging.Loggable; 9 | 10 | /** 11 | * The GrpcConfig class defines the configuration data for the gRPC client. 12 | * 13 | * @param serverAddress the address of the gRPC server 14 | * @param port the port of the gRPC server 15 | */ 16 | @ConfigData("grpc") 17 | public record GrpcConfig( 18 | @Loggable @ConfigProperty(defaultValue = "localhost") String serverAddress, 19 | @Loggable @ConfigProperty(defaultValue = "40840") @Min(0) @Max(65535) int port) {} 20 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/blockmessaging/VerificationNotification.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.blockmessaging; 3 | 4 | import com.hedera.pbj.runtime.io.buffer.Bytes; 5 | 6 | /** 7 | * Simple record for block verification notifications. 8 | * 9 | * @param success true if the block was verified successfully, false otherwise 10 | * @param blockNumber the block number this notification is for 11 | * @param blockHash the hash of the block, if the type is BLOCK_VERIFIED 12 | * @param block the block, if the type is BLOCK_VERIFIED 13 | * @param source the source of the message 14 | */ 15 | public record VerificationNotification( 16 | boolean success, 17 | long blockNumber, 18 | Bytes blockHash, 19 | org.hiero.block.internal.BlockUnparsed block, 20 | BlockSource source) {} 21 | -------------------------------------------------------------------------------- /docs/overview.md: -------------------------------------------------------------------------------- 1 | # Hiero Block Node Documentation Overview 2 | 3 | This document will outline the structure and content of Block Node documentation. 4 | 5 | ## Table of Contents 6 | 7 | 1. [Projects](#projects) 8 | 2. [Concepts](#concepts) 9 | 3. [Release](#release) 10 | 11 | ## Projects 12 | 13 | - [Hiero Block Node](block-node/README.md): Provides an introduction to Hiero Block Node, its purpose and how it can be used. 14 | - [Simulator](simulator/README.md): Offers instructions on how the Simulator can be utilized. 15 | - [Tools](tools/README.md): Provides information on the command line tools available. 16 | 17 | ## Concepts 18 | 19 | - [Hiero Block Node Protocol](design/communication-protocol/README.md): Overview of the Hiero Block Node Protocol 20 | 21 | ## Release 22 | 23 | - [Release Process Documentation](release.md): Details the steps involved in creating a new release, tagging, and publishing artifacts. 24 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/exception/BlockSimulatorParsingException.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.exception; 3 | 4 | /** Use this checked exception to represent a Block Simulator parsing exception. */ 5 | public class BlockSimulatorParsingException extends Exception { 6 | /** 7 | * Constructs a new parsing exception with the specified detail message. 8 | * 9 | * @param message the detail message 10 | */ 11 | public BlockSimulatorParsingException(final String message) { 12 | super(message); 13 | } 14 | 15 | /** 16 | * Constructs a new parsing exception with the specified cause. 17 | * 18 | * @param cause the cause of the exception, could be null, see super javadoc 19 | */ 20 | public BlockSimulatorParsingException(final Throwable cause) { 21 | super(cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /block-node/stream-publisher/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node Blocks Publisher Service" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("org.apache.logging.log4j.slf4j2.impl") 13 | runtimeOnly("io.helidon.logging.jul") 14 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 15 | } 16 | 17 | testModuleInfo { 18 | requires("com.swirlds.metrics.impl") 19 | requires("org.junit.jupiter.api") 20 | requires("org.junit.jupiter.params") 21 | requires("org.assertj.core") 22 | requires("org.hiero.block.node.app.test.fixtures") 23 | } 24 | -------------------------------------------------------------------------------- /block-node/blocks-file-recent/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node - Blocks File Recent Provider" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("org.apache.logging.log4j.slf4j2.impl") 13 | runtimeOnly("io.helidon.logging.jul") 14 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 15 | } 16 | 17 | testModuleInfo { 18 | requires("com.google.common.jimfs") 19 | requires("org.junit.jupiter.api") 20 | requires("org.junit.jupiter.params") 21 | requires("org.assertj.core") 22 | requires("org.hiero.block.node.app.test.fixtures") 23 | } 24 | -------------------------------------------------------------------------------- /block-node/base/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node Base" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("io.helidon.logging.jul") 13 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 14 | } 15 | 16 | testModuleInfo { 17 | requires("org.junit.jupiter.api") 18 | requires("org.junit.jupiter.params") 19 | requires("org.hiero.block.node.app.test.fixtures") 20 | requires("org.assertj.core") 21 | requires("org.mockito") 22 | requires("org.testcontainers") 23 | requires("io.minio") 24 | requires("org.hiero.block.protobuf.pbj") 25 | } 26 | -------------------------------------------------------------------------------- /block-node/facility-messaging/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node Messaging Facility" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("io.helidon.logging.jul") 13 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 14 | } 15 | 16 | testModuleInfo { 17 | requires("com.hedera.pbj.runtime") 18 | requires("org.hiero.block.protobuf.pbj") 19 | requires("java.logging") 20 | requires("org.junit.jupiter.api") 21 | requires("org.junit.jupiter.params") 22 | requires("com.swirlds.common") 23 | requires("org.hiero.block.node.app.test.fixtures") 24 | } 25 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/grafana-datasource.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | SPDX-License-Identifier: Apache-2.0 3 | */}} 4 | 5 | {{ if .Values.kubepromstack.enabled }} 6 | apiVersion: v1 7 | kind: ConfigMap 8 | metadata: 9 | name: {{ include "hiero-block-node.fullname" . }}-grafana-datasource 10 | labels: 11 | grafana_datasource: "1" 12 | data: 13 | datasource.yaml: | 14 | apiVersion: 2 15 | datasources: 16 | - name: Prometheus 17 | type: prometheus 18 | access: proxy 19 | url: http://{{ .Release.Name }}-kubepromstack-prometheus:9090 20 | isDefault: true 21 | editable: true 22 | jsonData: 23 | timeInterval: "15s" 24 | 25 | {{- if .Values.loki.enabled }} 26 | - name: Loki 27 | type: loki 28 | url: http://{{ .Release.Name }}-loki:3100 29 | access: proxy 30 | isDefault: false 31 | editable: true 32 | {{- end }} 33 | 34 | {{- end }} 35 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/blockmessaging/NoBackPressureBlockItemHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.blockmessaging; 3 | 4 | /** 5 | * This interface is used to handle block items without applying back pressure. If the handler can not keep up with the 6 | * incoming block items, it will receive a call on the {@link #onTooFarBehindError()} method. After that point the 7 | * handler will not get calls to {@link BlockItemHandler#handleBlockItemsReceived(BlockItems)} anymore. 8 | */ 9 | public interface NoBackPressureBlockItemHandler extends BlockItemHandler { 10 | /** 11 | * Called when the block item handler is too far behind the current block number. This can happen if the handler is 12 | * not able to process the block items fast enough. After this call, the handler will not receive any more block 13 | * items. 14 | */ 15 | void onTooFarBehindError(); 16 | } 17 | -------------------------------------------------------------------------------- /gradle/aggregation/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | dependencies { 3 | published(project(":protobuf-sources")) 4 | published(project(":app")) 5 | published(project(":app-config")) 6 | published(project(":backfill")) 7 | published(project(":base")) 8 | published(project(":block-access-service")) 9 | published(project(":blocks-file-historic")) 10 | published(project(":blocks-file-recent")) 11 | published(project(":health")) 12 | published(project(":facility-messaging")) 13 | published(project(":s3-archive")) 14 | published(project(":server-status")) 15 | published(project(":spi-plugins")) 16 | published(project(":stream-publisher")) 17 | published(project(":stream-subscriber")) 18 | published(project(":verification")) 19 | 20 | implementation(project(":app")) 21 | implementation(project(":simulator")) 22 | implementation(project(":suites")) 23 | implementation(project(":tools")) 24 | } 25 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/types/MidBlockFailType.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.types; 3 | 4 | /** The MidBlockFailType enum defines the type of failure in the process of block streaming. 5 | * Failure will occur randomly between the header and the proof of the block. */ 6 | public enum MidBlockFailType { 7 | /** 8 | * The NONE value indicates no failure will be simulated during streaming. 9 | */ 10 | NONE, 11 | /** 12 | * The ABRUPT value indicates that an abrupt disconnection will occur while streaming 13 | * (without closing the connection or sending an EndOfStream message). 14 | */ 15 | ABRUPT, 16 | /** 17 | * The EOS value indicates that an EndOfStream message will be sent before the final item of the block. 18 | * Currently, onError is called, as the client is not able to send actual EOS message 19 | */ 20 | EOS 21 | } 22 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/types/StreamingMode.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.types; 3 | 4 | /** The StreamingMode enum defines the different modes for streaming blocks. */ 5 | public enum StreamingMode { 6 | 7 | /** It will wait X Nanos between each block. */ 8 | CONSTANT_RATE, 9 | 10 | /** It will attempt to send a block each X Millis. */ 11 | MILLIS_PER_BLOCK; 12 | 13 | /** 14 | * Converts a string to a StreamingMode. 15 | * 16 | * @param mode the string to convert 17 | * @return the StreamingMode 18 | */ 19 | public static StreamingMode fromString(String mode) { 20 | return switch (mode) { 21 | case "CONSTANT_RATE" -> CONSTANT_RATE; 22 | case "MILLIS_PER_BLOCK" -> MILLIS_PER_BLOCK; 23 | default -> throw new IllegalArgumentException("Invalid mode: " + mode); 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /block-node/app-config/src/main/java/org/hiero/block/node/app/config/node/NodeConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app.config.node; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | import com.swirlds.config.api.validation.annotation.Min; 7 | import org.hiero.block.node.base.Loggable; 8 | 9 | /** 10 | * Use this configuration for Node-wide configuration. 11 | *

12 | * Node-wide configuration includes settings useful to _all_ or nearly all 13 | * plugins. Examples include the earliest block number managed by this node. 14 | * 15 | * @param earliestManagedBlock the block number for the earliest block managed 16 | * by this node. Blocks earlier than this might be present, but the node 17 | * should not make any particular effort to obtain or store them. 18 | */ 19 | @ConfigData("block.node") 20 | public record NodeConfig(@Loggable @ConfigProperty(defaultValue = "0") @Min(0) long earliestManagedBlock) {} 21 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | module org.hiero.block.node.spi { 3 | exports org.hiero.block.node.spi; 4 | exports org.hiero.block.node.spi.blockmessaging; 5 | exports org.hiero.block.node.spi.historicalblocks; 6 | exports org.hiero.block.node.spi.health; 7 | exports org.hiero.block.node.spi.threading; 8 | 9 | uses org.hiero.block.node.spi.blockmessaging.BlockMessagingFacility; 10 | uses org.hiero.block.node.spi.historicalblocks.BlockProviderPlugin; 11 | uses org.hiero.block.node.spi.BlockNodePlugin; 12 | 13 | requires transitive com.hedera.pbj.runtime; 14 | requires transitive com.swirlds.config.api; 15 | requires transitive com.swirlds.metrics.api; 16 | requires transitive org.hiero.block.protobuf.pbj; 17 | requires transitive io.helidon.webserver; 18 | requires static transitive com.github.spotbugs.annotations; 19 | requires static java.compiler; // javax.annotation.processing.Generated 20 | } 21 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/ServiceLoaderFunction.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi; 3 | 4 | import java.util.ServiceLoader; 5 | import java.util.stream.Stream; 6 | 7 | /** 8 | * The ServiceLoaderFunction class is used to load services using the Java ServiceLoader. Or alternatively a custom 9 | * implementation of when testing. 10 | */ 11 | public class ServiceLoaderFunction { 12 | /** 13 | * Load services of the given class. This method will use the Java ServiceLoader to load the services. Unless 14 | * overridden by a custom implementation. 15 | * 16 | * @param serviceClass the class of the service to load 17 | * @param the type of the service 18 | * @return a stream of services of the given class 19 | */ 20 | public Stream loadServices(Class serviceClass) { 21 | return ServiceLoader.load(serviceClass).stream().map(ServiceLoader.Provider::get); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | open module org.hiero.block.node.suites { 3 | requires com.hedera.pbj.grpc.client.helidon; 4 | requires com.hedera.pbj.runtime; 5 | requires com.swirlds.config.api; 6 | requires com.swirlds.config.extensions; 7 | requires org.hiero.block.node.app; 8 | requires org.hiero.block.node.spi; 9 | requires org.hiero.block.protobuf.protoc; 10 | requires org.hiero.block.simulator; 11 | requires com.github.dockerjava.api; 12 | requires io.grpc.stub; 13 | requires io.grpc; 14 | requires io.helidon.webclient.grpc; 15 | requires java.net.http; 16 | requires org.assertj.core; 17 | requires org.junit.jupiter.api; 18 | requires org.junit.jupiter.params; 19 | requires org.testcontainers; 20 | requires static com.github.spotbugs.annotations; 21 | requires static dagger; 22 | requires static io.helidon.webclient.api; 23 | requires static org.junit.platform.suite.api; 24 | } 25 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/ServiceBuilder.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi; 3 | 4 | import com.hedera.pbj.runtime.grpc.ServiceInterface; 5 | import edu.umd.cs.findbugs.annotations.NonNull; 6 | import io.helidon.webserver.http.HttpService; 7 | 8 | /** 9 | * ServiceBuilder is an interface that defines the contract for registering HTTP and gRPC services with the web server 10 | * during initialization. 11 | */ 12 | public interface ServiceBuilder { 13 | /** 14 | * Registers an HTTP service with the web server. 15 | * 16 | * @param path the path for the HTTP service 17 | * @param service the HTTP service to register 18 | */ 19 | void registerHttpService(String path, HttpService... service); 20 | 21 | /** 22 | * Registers a gRPC service with the web server. 23 | * 24 | * @param service the gRPC service to register 25 | */ 26 | void registerGrpcService(@NonNull ServiceInterface service); 27 | } 28 | -------------------------------------------------------------------------------- /block-node/verification/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.verification.VerificationServicePlugin; 3 | 4 | // SPDX-License-Identifier: Apache-2.0 5 | module org.hiero.block.node.verification { 6 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 7 | 8 | // export configuration classes to the config module and app 9 | exports org.hiero.block.node.verification to 10 | com.swirlds.config.impl, 11 | com.swirlds.config.extensions, 12 | org.hiero.block.node.app; 13 | 14 | requires transitive com.swirlds.config.api; 15 | requires transitive org.hiero.block.node.spi; 16 | requires com.hedera.pbj.runtime; 17 | requires com.swirlds.metrics.api; 18 | requires org.hiero.block.common; 19 | requires org.hiero.block.protobuf.pbj; 20 | requires com.github.spotbugs.annotations; 21 | 22 | provides org.hiero.block.node.spi.BlockNodePlugin with 23 | VerificationServicePlugin; 24 | } 25 | -------------------------------------------------------------------------------- /block-node/facility-messaging/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.messaging.BlockMessagingFacilityImpl; 3 | 4 | // SPDX-License-Identifier: Apache-2.0 5 | module org.hiero.block.node.messaging { 6 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 7 | 8 | // export configuration classes to the config module 9 | exports org.hiero.block.node.messaging to 10 | com.swirlds.config.impl, 11 | com.swirlds.config.extensions, 12 | org.hiero.block.node.app; 13 | 14 | requires transitive com.swirlds.config.api; 15 | requires transitive org.hiero.block.node.spi; 16 | requires com.swirlds.metrics.api; 17 | requires org.hiero.block.common; 18 | requires org.hiero.block.node.base; 19 | requires com.github.spotbugs.annotations; 20 | requires com.lmax.disruptor; 21 | 22 | provides org.hiero.block.node.spi.blockmessaging.BlockMessagingFacility with 23 | BlockMessagingFacilityImpl; 24 | } 25 | -------------------------------------------------------------------------------- /tools-and-tests/protobuf-protoc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { 3 | id("org.hiero.gradle.module.library") 4 | id("org.hiero.gradle.feature.protobuf") 5 | } 6 | 7 | description = "Hiero Block Node Protobuf Protoc API" 8 | 9 | sourceSets { 10 | main { 11 | proto { 12 | // use sources from 'protobuf' module 13 | srcDir(layout.projectDirectory.dir("../../protobuf-sources/src/main/proto")) 14 | // use sources from CN repository cloned by 'protobuf' module (see task dependency) 15 | srcDir(layout.projectDirectory.dir("../../protobuf-sources/block-node-protobuf")) 16 | // exclude BN files at root level 17 | exclude("*.proto") 18 | } 19 | } 20 | } 21 | 22 | // jjohannes: remove cross-project task dependency once the following issue is addressed 23 | // https://github.com/hiero-ledger/hiero-gradle-conventions/issues/185 24 | tasks.generateProto { dependsOn(":protobuf-sources:generateBlockNodeProtoArtifact") } 25 | -------------------------------------------------------------------------------- /docs/design/communication-protocol/README.md: -------------------------------------------------------------------------------- 1 | # Protocol Documents 2 | 3 | This folder contains documents describing the expected protocol for various 4 | APIs provided by the Block Node and related systems. 5 | Each protocol document should describe a single API call and the expected 6 | behavior of both sides of that API call, including common error conditions. 7 | 8 | ## Contents 9 | 10 | | Document | API call | Description | 11 | |:-------------------------------------------------|---------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------| 12 | | [publishBlockStream.md](publish-block-stream.md) | `publishBlockStream` | The communication between a publisher and a Block Node when publishing a Block Stream from an authoritative source such as a Consensus Node. | 13 | -------------------------------------------------------------------------------- /block-node/app/src/testFixtures/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | module org.hiero.block.node.app.test.fixtures { 3 | exports org.hiero.block.node.app.fixtures; 4 | exports org.hiero.block.node.app.fixtures.async; 5 | exports org.hiero.block.node.app.fixtures.blocks; 6 | exports org.hiero.block.node.app.fixtures.pipeline; 7 | exports org.hiero.block.node.app.fixtures.plugintest; 8 | exports org.hiero.block.node.app.fixtures.server; 9 | 10 | requires com.hedera.pbj.grpc.helidon.config; 11 | requires com.hedera.pbj.grpc.helidon; 12 | requires com.hedera.pbj.runtime; 13 | requires com.swirlds.common; 14 | requires com.swirlds.config.api; 15 | requires com.swirlds.metrics.api; 16 | requires org.hiero.block.node.app.config; 17 | requires org.hiero.block.node.spi; 18 | requires org.hiero.block.protobuf.pbj; 19 | requires com.github.luben.zstd_jni; 20 | requires io.helidon.webserver; 21 | requires java.logging; 22 | requires org.junit.jupiter.api; 23 | } 24 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/grpc/PublishStreamGrpcServer.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.grpc; 3 | 4 | import java.util.List; 5 | 6 | public interface PublishStreamGrpcServer { 7 | /** 8 | * Initialize, opens a gRPC channel and creates the needed services with the passed configuration. 9 | */ 10 | void init(); 11 | 12 | /** 13 | * Starts the gRPC server. 14 | */ 15 | void start(); 16 | 17 | /** 18 | * Gets the number of processed blocks. 19 | * 20 | * @return the number of published blocks 21 | */ 22 | long getProcessedBlocks(); 23 | 24 | /** 25 | * Gets the last known statuses. 26 | * 27 | * @return the last known statuses 28 | */ 29 | List getLastKnownStatuses(); 30 | 31 | /** 32 | * Shutdowns the server. 33 | * 34 | * @throws InterruptedException if the thread is interrupted 35 | */ 36 | void shutdown() throws InterruptedException; 37 | } 38 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/persistence/DataPersistenceTestSuites.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites.persistence; 3 | 4 | import org.hiero.block.suites.persistence.positive.PositiveDataPersistenceTests; 5 | import org.junit.platform.suite.api.SelectClasses; 6 | import org.junit.platform.suite.api.Suite; 7 | 8 | /** 9 | * Test suite for running data persistence tests, including both positive and negative test 10 | * scenarios. 11 | * 12 | *

This suite aggregates the tests from {@link PositiveDataPersistenceTests}. The {@code @Suite} 13 | * annotation allows running all selected classes in a single test run. 14 | */ 15 | @Suite 16 | @SelectClasses({PositiveDataPersistenceTests.class}) 17 | public class DataPersistenceTestSuites { 18 | 19 | /** 20 | * Default constructor for the {@link DataPersistenceTestSuites} class. This constructor is 21 | * empty as it does not need to perform any initialization. 22 | */ 23 | public DataPersistenceTestSuites() {} 24 | } 25 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/publisher/PublisherTestSuites.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites.publisher; 3 | 4 | import org.hiero.block.suites.publisher.positive.PositiveMultiplePublishersTests; 5 | import org.junit.platform.suite.api.SelectClasses; 6 | import org.junit.platform.suite.api.Suite; 7 | 8 | /** 9 | * Test suite for running multiple publishers tests, including both positive and negative test 10 | * scenarios. 11 | * 12 | *

This suite aggregates the tests from {@link PositiveMultiplePublishersTests}. The {@code @Suite} 13 | * annotation allows running all selected classes in a single test run. 14 | */ 15 | @Suite 16 | @SelectClasses({PositiveMultiplePublishersTests.class}) 17 | public class PublisherTestSuites { 18 | /** 19 | * Default constructor for the {@link org.hiero.block.suites.publisher.PublisherTestSuites} class. This constructor is 20 | * empty as it does not need to perform any initialization. 21 | */ 22 | public PublisherTestSuites() {} 23 | } 24 | -------------------------------------------------------------------------------- /block-node/stream-subscriber/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.stream.subscriber.SubscriberServicePlugin; 3 | 4 | // SPDX-License-Identifier: Apache-2.0 5 | module org.hiero.block.node.stream.subscriber { 6 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 7 | 8 | // export configuration classes to the config module and app 9 | exports org.hiero.block.node.stream.subscriber to 10 | com.swirlds.config.impl, 11 | com.swirlds.config.extensions, 12 | org.hiero.block.node.app; 13 | 14 | requires transitive com.hedera.pbj.runtime; 15 | requires transitive com.swirlds.config.api; 16 | requires transitive org.hiero.block.node.spi; 17 | requires transitive org.hiero.block.protobuf.pbj; 18 | requires com.swirlds.metrics.api; 19 | requires org.hiero.block.node.base; 20 | requires com.github.spotbugs.annotations; 21 | 22 | provides org.hiero.block.node.spi.BlockNodePlugin with 23 | SubscriberServicePlugin; 24 | } 25 | -------------------------------------------------------------------------------- /block-node/blocks-file-recent/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.blocks.files.recent.BlockFileRecentPlugin; 3 | 4 | // SPDX-License-Identifier: Apache-2.0 5 | module org.hiero.block.node.blocks.files.recent { 6 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 7 | 8 | // export configuration classes to the config module and app 9 | exports org.hiero.block.node.blocks.files.recent to 10 | com.swirlds.config.impl, 11 | com.swirlds.config.extensions, 12 | org.hiero.block.node.app; 13 | 14 | requires transitive com.swirlds.config.api; 15 | requires transitive org.hiero.block.node.base; 16 | requires transitive org.hiero.block.node.spi; 17 | requires com.hedera.pbj.runtime; 18 | requires com.swirlds.metrics.api; 19 | requires org.hiero.block.protobuf.pbj; 20 | requires com.github.spotbugs.annotations; 21 | 22 | provides org.hiero.block.node.spi.historicalblocks.BlockProviderPlugin with 23 | BlockFileRecentPlugin; 24 | } 25 | -------------------------------------------------------------------------------- /block-node/blocks-file-historic/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { id("org.hiero.gradle.module.library") } 3 | 4 | description = "Hiero Block Node - Blocks File Historic Provider" 5 | 6 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 7 | // and then fix the reported issues. 8 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 9 | 10 | mainModuleInfo { 11 | runtimeOnly("com.swirlds.config.impl") 12 | runtimeOnly("org.apache.logging.log4j.slf4j2.impl") 13 | runtimeOnly("io.helidon.logging.jul") 14 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 15 | } 16 | 17 | testModuleInfo { 18 | requires("com.google.common.jimfs") 19 | requires("org.junit.jupiter.api") 20 | requires("org.junit.jupiter.params") 21 | requires("org.assertj.core") 22 | requires("org.hiero.block.node.app.test.fixtures") 23 | runtimeOnly("com.swirlds.metrics.api") 24 | requires("org.mockito") 25 | runtimeOnly("org.mockito.junit.jupiter") 26 | } 27 | -------------------------------------------------------------------------------- /charts/block-node-server/Chart.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | apiVersion: v2 3 | appVersion: 0.26.0-SNAPSHOT 4 | description: A Helm chart for Hiero Block Node 5 | home: https://github.com/hiero-ledger/hiero-block-node 6 | keywords: 7 | - blocknode 8 | - dlt 9 | - hiero 10 | - hedera 11 | - hashgraph 12 | maintainers: 13 | - name: Hiero Block Node Team 14 | email: blocknode@hashgraph.com 15 | name: block-node-server 16 | sources: 17 | - https://github.com/hiero-ledger/hiero-block-node 18 | version: 0.26.0-SNAPSHOT 19 | dependencies: 20 | - name: kube-prometheus-stack 21 | alias: kubepromstack 22 | condition: kubepromstack.enabled 23 | version: "78.4.0" # Use the latest stable version 24 | repository: "https://prometheus-community.github.io/helm-charts" 25 | - name: "loki" 26 | condition: loki.enabled 27 | repository: "https://grafana.github.io/helm-charts" 28 | version: "^2.15.2" 29 | - name: "promtail" 30 | condition: promtail.enabled 31 | repository: "https://grafana.github.io/helm-charts" 32 | version: "^6.7.4" 33 | -------------------------------------------------------------------------------- /charts/block-node-server/values-overrides/rfh-values.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | requests: 3 | cpu: "6" 4 | memory: "16Gi" 5 | 6 | blockNode: 7 | secretRef: "bn--s3-creds" 8 | config: 9 | JAVA_OPTS: '-Xms8G -Xmx8G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="/tmp/dump.hprof"' 10 | # Change the following Value with the next expected Block to be 11 | # published by the Network. 12 | # BLOCK_NODE_EARLIEST_MANAGED_BLOCK: "0" 13 | # Archive Node Configuration 14 | ARCHIVE_BLOCKS_PER_FILE: "10000" # Default is 100_000 15 | ARCHIVE_BUCKET_NAME: "bn-eng-archive-bucket" 16 | ARCHIVE_ENDPOINT_URL: "https://storage.googleapis.com" 17 | ARCHIVE_BASE_PATH: "previewnet/archive1" 18 | ARCHIVE_STORAGE_CLASS: "ARCHIVE" 19 | ARCHIVE_REGION_NAME: "us-central1" 20 | 21 | persistence: 22 | archive: 23 | size: 50Gi 24 | live: 25 | size: 10Gi 26 | logging: 27 | size: 2Gi 28 | -------------------------------------------------------------------------------- /block-node/s3-archive/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.archive.s3.S3ArchivePlugin; 3 | 4 | // SPDX-License-Identifier: Apache-2.0 5 | module org.hiero.block.node.archive.s3cloud { 6 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 7 | 8 | // export configuration classes to the config module and app 9 | exports org.hiero.block.node.archive.s3 to 10 | com.swirlds.config.impl, 11 | com.swirlds.config.extensions, 12 | org.hiero.block.node.app; 13 | 14 | requires transitive com.swirlds.config.api; 15 | requires transitive org.hiero.block.node.spi; 16 | requires com.hedera.pbj.runtime; 17 | requires org.hiero.block.common; 18 | requires org.hiero.block.node.base; 19 | requires org.hiero.block.protobuf.pbj; 20 | requires com.github.spotbugs.annotations; 21 | requires java.management; 22 | requires java.net.http; 23 | requires java.xml; 24 | 25 | provides org.hiero.block.node.spi.BlockNodePlugin with 26 | S3ArchivePlugin; 27 | } 28 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/types/EndStreamMode.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.types; 3 | 4 | /** 5 | * Enum representing EndStream modes. 6 | */ 7 | public enum EndStreamMode { 8 | /** 9 | * Indicates that EndStream will not be sent. 10 | */ 11 | NONE, 12 | /** 13 | * Indicates that RESET will be sent. 14 | * Occasionally resetting the stream increases stability and allows for routine network configuration changes. 15 | */ 16 | RESET, 17 | 18 | /** 19 | * Indicates that TIMEOUT will be sent. 20 | * The delay between items was too long. The destination system did not timely acknowledge a block. 21 | */ 22 | TIMEOUT, 23 | 24 | /** 25 | * Indicates that ERROR will be sent. 26 | * The Publisher encountered an error. 27 | */ 28 | ERROR, 29 | 30 | /** 31 | * Indicates that TOO_FAR_BEHIND will be sent. 32 | * This is used to simulate when the block node is too far behind with blocks. 33 | */ 34 | TOO_FAR_BEHIND 35 | } 36 | -------------------------------------------------------------------------------- /block-node/stream-publisher/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.stream.publisher.StreamPublisherPlugin; 3 | 4 | // SPDX-License-Identifier: Apache-2.0 5 | module org.hiero.block.node.stream.publisher { 6 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 7 | 8 | // export configuration classes to the config module and app 9 | exports org.hiero.block.node.stream.publisher to 10 | com.swirlds.config.impl, 11 | com.swirlds.config.extensions, 12 | org.hiero.block.node.app; 13 | 14 | requires transitive com.hedera.pbj.runtime; 15 | requires transitive com.swirlds.config.api; 16 | requires transitive com.swirlds.metrics.api; 17 | requires transitive org.hiero.block.node.spi; 18 | requires transitive org.hiero.block.protobuf.pbj; 19 | requires org.hiero.block.node.app.config; 20 | requires org.hiero.block.node.base; 21 | requires com.github.spotbugs.annotations; 22 | 23 | provides org.hiero.block.node.spi.BlockNodePlugin with 24 | StreamPublisherPlugin; 25 | } 26 | -------------------------------------------------------------------------------- /block-node/blocks-file-historic/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.blocks.files.historic.BlockFileHistoricPlugin; 3 | 4 | // SPDX-License-Identifier: Apache-2.0 5 | module org.hiero.block.node.blocks.files.historic { 6 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 7 | 8 | // export configuration classes to the config module and app 9 | exports org.hiero.block.node.blocks.files.historic to 10 | com.swirlds.config.impl, 11 | com.swirlds.config.extensions, 12 | org.hiero.block.node.app; 13 | 14 | requires transitive com.swirlds.config.api; 15 | requires transitive org.hiero.block.node.base; 16 | requires transitive org.hiero.block.node.spi; 17 | requires com.hedera.pbj.runtime; 18 | requires com.swirlds.metrics.api; 19 | requires org.hiero.block.common; 20 | requires org.hiero.block.protobuf.pbj; 21 | requires com.github.spotbugs.annotations; 22 | 23 | provides org.hiero.block.node.spi.historicalblocks.BlockProviderPlugin with 24 | BlockFileHistoricPlugin; 25 | } 26 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/historicalblocks/HistoricalBlockFacility.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.historicalblocks; 3 | 4 | import org.hiero.block.node.spi.BlockNodePlugin; 5 | 6 | /** 7 | * The HistoricalBlockFacility interface is used to provide access to historical blocks to the different parts of the 8 | * block node. The range from the oldest block to the newest block is an inclusive range. 9 | */ 10 | @SuppressWarnings("unused") 11 | public interface HistoricalBlockFacility extends BlockNodePlugin { 12 | 13 | /** 14 | * Use this method to get the block at the specified block number. 15 | * 16 | * @param blockNumber the block number 17 | * @return the block at the specified block number, null if the block is not available 18 | */ 19 | BlockAccessor block(long blockNumber); 20 | 21 | /** 22 | * Use this method to get the set of all blocks available in this block node. 23 | * 24 | * @return the set of all blocks available in this block node 25 | */ 26 | BlockRangeSet availableBlocks(); 27 | } 28 | -------------------------------------------------------------------------------- /block-node/verification/src/main/java/org/hiero/block/node/verification/session/VerificationSession.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.verification.session; 3 | 4 | import com.hedera.pbj.runtime.ParseException; 5 | import java.util.List; 6 | import org.hiero.block.internal.BlockItemUnparsed; 7 | import org.hiero.block.node.spi.blockmessaging.VerificationNotification; 8 | 9 | /** 10 | * A session for verifying a single block. A new session is created for each block to verify. 11 | */ 12 | public interface VerificationSession { 13 | /** 14 | * Processes the provided block items by updating the tree hashers. 15 | * If the last item has a block proof, final verification is triggered. 16 | * 17 | * @param blockItems the block items to process 18 | * @return VerificationNotification indicating the result of the verification if these items included the final 19 | * block proof otherwise null 20 | * @throws ParseException if a parsing error occurs 21 | */ 22 | VerificationNotification processBlockItems(List blockItems) throws ParseException; 23 | } 24 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/subscriber/SubscriberTestSuites.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites.subscriber; 3 | 4 | import org.hiero.block.suites.subscriber.negative.NegativeSingleSubscriberTests; 5 | import org.hiero.block.suites.subscriber.positive.PositiveSingleSubscriberTests; 6 | import org.junit.platform.suite.api.SelectClasses; 7 | import org.junit.platform.suite.api.Suite; 8 | 9 | /** 10 | * Test suite for running subscriber tests, including both positive and negative test scenarios. 11 | * 12 | *

This suite aggregates the tests related to the subscriber functionality. The {@code @Suite} annotation allows running all selected classes in a single test run.

13 | */ 14 | @Suite 15 | @SelectClasses({PositiveSingleSubscriberTests.class, NegativeSingleSubscriberTests.class}) 16 | public class SubscriberTestSuites { 17 | /** 18 | * Default constructor for the {@link PositiveSingleSubscriberTests} class.This constructor is 19 | * empty as it does not need to perform any initialization. 20 | */ 21 | public SubscriberTestSuites() {} 22 | } 23 | -------------------------------------------------------------------------------- /tools-and-tests/tools/src/main/java/org/hiero/block/tools/config/proto/network_capacity_config.proto: -------------------------------------------------------------------------------- 1 | 2 | // SPDX-License-Identifier: Apache-2.0 3 | syntax = "proto3"; 4 | 5 | package org.hiero.block.tools.config; 6 | 7 | message HelidonWebClientConfig { 8 | uint32 flowControlTimeoutMillis = 1; 9 | uint32 initialWindowSize = 2; 10 | uint32 maxFrameSize = 3; 11 | uint32 maxHeaderListSize = 4; 12 | bool pingEnabled = 5; 13 | uint32 pingTimeoutMillis = 6; 14 | uint32 readTimeoutMillis = 7; 15 | bool priorKnowledge = 10; 16 | uint32 serverMaxMessageSizeBytes = 12; 17 | uint32 delayBetweenBlocksMs = 13; 18 | } 19 | 20 | message HelidonWebServerConfig { 21 | uint32 initialWindowSize = 1; 22 | uint32 maxFrameSize = 2; 23 | uint32 maxConcurrentStreams = 3; 24 | uint32 flowControlTimeoutMillis = 4; 25 | uint32 sendBufferSize = 5; 26 | uint32 receiveBufferSize = 6; 27 | uint32 maxMessageSizeBytes = 7; 28 | bool tcpNoDelay = 8; 29 | uint32 maxEmptyFrames = 9; 30 | uint32 maxRapidResets = 10; 31 | uint32 rapidResetTimeWindowMillis = 11; 32 | uint32 backlogSize = 12; 33 | uint32 writeQueueLength = 13; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/generator/itemhandler/ItemHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.generator.itemhandler; 3 | 4 | import com.hedera.hapi.block.stream.protoc.BlockItem; 5 | import org.hiero.block.internal.BlockItemUnparsed; 6 | import org.hiero.block.simulator.exception.BlockSimulatorParsingException; 7 | 8 | /** 9 | * Interface defining the contract for handling different types of block items. 10 | * Implementations handle specific types of items like block headers, proofs, events, and transactions. 11 | */ 12 | public interface ItemHandler { 13 | /** 14 | * Returns the block item in its protobuf format. 15 | * 16 | * @return The constructed BlockItem 17 | */ 18 | BlockItem getItem(); 19 | 20 | /** 21 | * Converts the block item to its unparsed format. 22 | * 23 | * @return The block item in unparsed format 24 | * @throws BlockSimulatorParsingException if there is an error parsing the block item 25 | */ 26 | BlockItemUnparsed unparseBlockItem() throws BlockSimulatorParsingException; 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/org/hiero/block/common/utils/StringUtilities.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.common.utils; 3 | 4 | import java.util.Objects; 5 | 6 | /** A utility class that deals with logic related to Strings. */ 7 | public final class StringUtilities { 8 | /** Empty {@link String} constant. Non-null, but with no whitespaces. */ 9 | public static final String EMPTY = ""; 10 | 11 | /** 12 | * This method takes an input {@link String} and checks if it is blank. 13 | * A {@link String} is considered blank if it is either {@code null} or 14 | * contains only whitespace characters as defined by 15 | * {@link String#isBlank()}. 16 | * 17 | * @param toCheck a {@link String} to check if it is blank 18 | * @return {@code true} if the given {@link String} to check is either 19 | * {@code null} or contains only whitespace characters, {@code false} 20 | * otherwise 21 | */ 22 | public static boolean isBlank(final String toCheck) { 23 | return Objects.isNull(toCheck) || toCheck.isBlank(); 24 | } 25 | 26 | private StringUtilities() {} 27 | } 28 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:21 2 | 3 | # Create a non-root user and group 4 | ARG UNAME=hedera 5 | ARG UID=2000 6 | ARG GID=2000 7 | ARG BN_WORKDIR="/opt/hiero/block-node" 8 | ENV BN_WORKDIR=${BN_WORKDIR} 9 | RUN groupadd --gid $GID $UNAME 10 | RUN useradd --no-user-group --create-home --uid $UID --gid $GID --shell /bin/bash hedera 11 | WORKDIR ${BN_WORKDIR} 12 | 13 | # Copy the distribution and resources 14 | COPY simulator-*.tar ./simulator.tar 15 | 16 | RUN mkdir -p ${BN_WORKDIR}/logs/config 17 | COPY logging.properties ${BN_WORKDIR}/logs/config/logging.properties 18 | 19 | # Extract the distribution and block data 20 | RUN tar -xf simulator.tar && \ 21 | rm simulator.tar && \ 22 | cd ${BN_WORKDIR} && \ 23 | chown -R $UID:$GID ${BN_WORKDIR} 24 | 25 | # Switch to non-root user 26 | USER $UNAME 27 | 28 | # Run the simulator using the extracted directory name 29 | RUN SIMULATOR_DIR=$(ls -d simulator-*/) && \ 30 | echo "#!/bin/bash\n${BN_WORKDIR}/${SIMULATOR_DIR}bin/simulator" > ${BN_WORKDIR}/start.sh && \ 31 | chmod +x ${BN_WORKDIR}/start.sh 32 | 33 | ENTRYPOINT ["sh","-c","${BN_WORKDIR}/start.sh"] 34 | -------------------------------------------------------------------------------- /block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/plugintest/NoOpServiceBuilder.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app.fixtures.plugintest; 3 | 4 | import com.hedera.pbj.runtime.grpc.ServiceInterface; 5 | import edu.umd.cs.findbugs.annotations.NonNull; 6 | import io.helidon.webserver.http.HttpService; 7 | import org.hiero.block.node.spi.ServiceBuilder; 8 | 9 | /** 10 | * A simple no-op implementation of {@link ServiceBuilder} that does nothing. 11 | * To be used for testing purposes only where we need a non-null implementation 12 | * that we do not want to act upon. 13 | */ 14 | public final class NoOpServiceBuilder implements ServiceBuilder { 15 | /** 16 | * No-op implementation, does nothing. 17 | */ 18 | @Override 19 | public void registerHttpService(final String path, final HttpService... service) { 20 | // No-op implementation, does nothing. 21 | } 22 | 23 | /** 24 | * No-op implementation, does nothing. 25 | */ 26 | @Override 27 | public void registerGrpcService(@NonNull final ServiceInterface service) { 28 | // No-op implementation, does nothing. 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /docs/configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | The Hiero Block Node repo is composed of multiple components that can be configured using the following options: 4 | 5 | ## Default Configuration 6 | 7 | The default configuration allows users to quickly get up and running without having to configure anything. This provides 8 | ease of use at the trade-off of some insecure default configuration. Most configuration settings have appropriate 9 | defaults and can be left unchanged. It is recommended to browse the properties below and adjust to your needs. 10 | 11 | The configuration facility of the Hiero Block Node supports overriding configuration values via environment variables, 12 | with a well-defined transform from property name to environment variable name. 13 | 14 | > **Note:** The default configuration should be considered a "production" recommendation, and we may provide separate 15 | > recommended "overrides" for development, test, etc... 16 | 17 | ## Server 18 | 19 | Server configuration options are described at [Server Configuration](block-node/configuration.md). 20 | 21 | ## Simulator 22 | 23 | Simulator configuration options are described at [Simulator Configuration](simulator/configuration.md). 24 | -------------------------------------------------------------------------------- /tools-and-tests/k6/lib/grpc.js: -------------------------------------------------------------------------------- 1 | import {Stream} from "k6/net/grpc"; 2 | 3 | class ServerStatusRequest { 4 | constructor(client) { 5 | this.client = client; 6 | this.protoDef = 'org.hiero.block.api.BlockNodeService/serverStatus' 7 | } 8 | 9 | invoke(params = {}) { 10 | const req = {}; 11 | return this.client.invoke(this.protoDef, req, params); 12 | } 13 | } 14 | 15 | class GetBlockRequest { 16 | constructor(client) { 17 | this.client = client; 18 | this.protoDef = 'org.hiero.block.api.BlockAccessService/getBlock' 19 | } 20 | 21 | invoke(blockNumber, params = {}) { 22 | const req = {block_number: blockNumber}; 23 | return this.client.invoke(this.protoDef, req, params) 24 | } 25 | } 26 | 27 | class SubscribeBlockStreamRequest { 28 | constructor(client) { 29 | this.client = client; 30 | this.protoDef = 'org.hiero.block.api.BlockStreamSubscribeService/subscribeBlockStream' 31 | } 32 | 33 | invoke(params = {}) { 34 | return new Stream(this.client, this.protoDef , params); 35 | } 36 | } 37 | 38 | export { ServerStatusRequest, GetBlockRequest, SubscribeBlockStreamRequest }; 39 | 40 | -------------------------------------------------------------------------------- /charts/block-node-server/values-overrides/mini.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | # This override values for the block-node-server chart to deploy a mini version of the block-node-server. 4 | # This is useful for testing and development purposes with limited resources. 5 | # ie: minikube 6 | 7 | resources: 8 | requests: 9 | cpu: "4" 10 | memory: "8Gi" 11 | 12 | blockNode: 13 | config: 14 | JAVA_OPTS: '-Xms4G -Xmx4G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="/tmp/dump.hprof"' 15 | MESSAGING_BLOCK_ITEM_QUEUE_SIZE: "512" 16 | MESSAGING_BLOCK_NOTIFICATION_QUEUE_SIZE: "32" 17 | BACKFILL_FETCH_BATCH_SIZE: "10" 18 | persistence: 19 | archive: 20 | size: 6Gi 21 | live: 22 | size: 1Gi 23 | logging: 24 | size: 1Gi 25 | 26 | # Setting the PVC size for the Observability stack to mini claims of 1 Gigabyte 27 | kubepromstack: 28 | prometheus: 29 | prometheusSpec: 30 | storageSpec: 31 | volumeClaimTemplate: 32 | spec: 33 | resources: 34 | requests: 35 | storage: 1Gi 36 | grafana: 37 | persistence: 38 | size: 1Gi 39 | 40 | loki: 41 | persistence: 42 | size: 1Gi 43 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/service-loadbalancer.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | SPDX-License-Identifier: Apache-2.0 3 | */}} 4 | 5 | {{- if .Values.loadBalancer.enabled }} 6 | apiVersion: v1 7 | kind: Service 8 | metadata: 9 | name: {{ default (printf "%s-external" (include "hiero-block-node.fullname" .)) .Values.loadBalancer.nameOverride }} 10 | labels: 11 | {{- include "hiero-block-node.labels" . | nindent 4 }} 12 | {{- with .Values.loadBalancer.annotations }} 13 | annotations: 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | spec: 17 | type: LoadBalancer 18 | {{- with .Values.loadBalancer.loadBalancerIP }} 19 | loadBalancerIP: {{ . | quote }} 20 | {{- end }} 21 | selector: 22 | {{- include "hiero-block-node.selectorLabels" . | nindent 4 }} 23 | ports: 24 | - name: {{ default "grpc" .Values.loadBalancer.portName }} 25 | port: {{ default .Values.service.port .Values.loadBalancer.port }} 26 | targetPort: {{ default "http" .Values.loadBalancer.targetPort }} 27 | protocol: {{ default "TCP" .Values.loadBalancer.protocol }} 28 | {{- with .Values.loadBalancer.loadBalancerSourceRanges }} 29 | loadBalancerSourceRanges: 30 | {{- toYaml . | nindent 4 }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/generator/itemhandler/EventHeaderHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.generator.itemhandler; 3 | 4 | import com.hedera.hapi.block.stream.input.protoc.EventHeader; 5 | import com.hedera.hapi.block.stream.protoc.BlockItem; 6 | import com.hedera.hapi.platform.event.legacy.EventCore; 7 | 8 | /** 9 | * Handler for event headers in the block stream. 10 | * Creates and manages event header items containing metadata about events. 11 | */ 12 | public class EventHeaderHandler extends AbstractBlockItemHandler { 13 | @Override 14 | public BlockItem getItem() { 15 | if (blockItem == null) { 16 | blockItem = 17 | BlockItem.newBuilder().setEventHeader(createEventHeader()).build(); 18 | } 19 | return blockItem; 20 | } 21 | 22 | private EventHeader createEventHeader() { 23 | return EventHeader.newBuilder().setEventCore(createEventCore()).build(); 24 | } 25 | 26 | private EventCore createEventCore() { 27 | return EventCore.newBuilder() 28 | .setCreatorNodeId(generateRandomValue(1, 32)) 29 | .build(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | bin/ 13 | 14 | # Package Files # 15 | *.jar 16 | *.war 17 | *.nar 18 | *.ear 19 | *.zip 20 | *.tar.gz 21 | *.rar 22 | 23 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 24 | hs_err_pid* 25 | replay_pid* 26 | 27 | # Gradle files 28 | .gradle 29 | **/build/ 30 | !src/**/build/ 31 | 32 | # Ignore Gradle GUI config 33 | gradle-app.setting 34 | 35 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 36 | !gradle-wrapper.jar 37 | 38 | # Avoid ignore Gradle wrapper properties 39 | !gradle-wrapper.properties 40 | 41 | # Cache of project 42 | .gradletasknamecache 43 | 44 | # Eclipse Gradle plugin generated files 45 | # Eclipse Core 46 | .project 47 | 48 | # JDT-specific (Eclipse Java Development Tools) 49 | .classpath 50 | 51 | .idea 52 | .DS_Store 53 | 54 | # .env files (from anywhere) 55 | .env 56 | 57 | server/data/ 58 | /tools/data/ 59 | 60 | # manual test files 61 | server/src/test/resources/test_output/ 62 | 63 | # protobuf artifcate related dirs 64 | protobuf-sources/block-node-protobuf/ 65 | protobuf-sources/hiero-consensus-node/ 66 | 67 | node_modules/ 68 | k6-proto/ 69 | k6-out.txt 70 | -------------------------------------------------------------------------------- /block-node/app/docker/promtail-config.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | http_listen_port: 9080 3 | grpc_listen_port: 0 4 | clients: 5 | - url: http://loki:3100/loki/api/v1/push 6 | positions: 7 | filename: /tmp/positions.yaml 8 | scrape_configs: 9 | # Docker Service Discovery 10 | - job_name: docker-logs 11 | docker_sd_configs: 12 | - host: unix:///var/run/docker.sock 13 | pipeline_stages: 14 | - docker: 15 | docker_url: unix:///var/run/docker.sock 16 | # This multiline stage merges multiple lines for one exception stack trace 17 | # into a single log message. 18 | - multiline: 19 | # firstline: A regex that identifies the start of a new log entry 20 | firstline: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}' 21 | # Maximum wait time for more lines before sending the collected log upstream 22 | max_wait_time: 3s 23 | relabel_configs: 24 | - source_labels: [__meta_docker_container_name] 25 | regex: "/(.*)" 26 | replacement: "$1" 27 | target_label: container_name 28 | - source_labels: [__meta_docker_container_image] 29 | target_label: image 30 | - source_labels: [__meta_docker_container_id] 31 | target_label: container_id 32 | - target_label: job 33 | replacement: docker-logs 34 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/generator/itemhandler/SignedTransactionHandlerTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.generator.itemhandler; 3 | 4 | import static org.junit.jupiter.api.Assertions.assertNotNull; 5 | import static org.junit.jupiter.api.Assertions.assertSame; 6 | import static org.junit.jupiter.api.Assertions.assertTrue; 7 | 8 | import com.google.protobuf.ByteString; 9 | import com.hedera.hapi.block.stream.protoc.BlockItem; 10 | import org.junit.jupiter.api.Test; 11 | 12 | class SignedTransactionHandlerTest { 13 | 14 | @Test 15 | void testGetItem() { 16 | SignedTransactionHandler handler = new SignedTransactionHandler(); 17 | BlockItem item = handler.getItem(); 18 | 19 | assertNotNull(item); 20 | assertTrue(item.hasSignedTransaction()); 21 | 22 | ByteString transaction = item.getSignedTransaction(); 23 | assertNotNull(transaction); 24 | } 25 | 26 | @Test 27 | void testGetItemCaching() { 28 | SignedTransactionHandler handler = new SignedTransactionHandler(); 29 | BlockItem item1 = handler.getItem(); 30 | BlockItem item2 = handler.getItem(); 31 | 32 | assertSame(item1, item2, "getItem should return cached instance"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tools-and-tests/suites/src/main/java/org/hiero/block/suites/grpc/GrpcTestSuites.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.suites.grpc; 3 | 4 | import org.hiero.block.suites.grpc.negative.NegativeServerAvailabilityTests; 5 | import org.hiero.block.suites.grpc.positive.PositiveEndpointBehaviourTests; 6 | import org.hiero.block.suites.grpc.positive.PositiveServerAvailabilityTests; 7 | import org.junit.platform.suite.api.SelectClasses; 8 | import org.junit.platform.suite.api.Suite; 9 | 10 | /** 11 | * Test suite for running gRPC server availability tests, including both positive and negative test 12 | * scenarios. 13 | * 14 | *

This suite aggregates the tests from {@link PositiveServerAvailabilityTests} and {@link 15 | * NegativeServerAvailabilityTests}. The {@code @Suite} annotation allows running all selected 16 | * classes in a single test run. 17 | */ 18 | @Suite 19 | @SelectClasses({ 20 | PositiveServerAvailabilityTests.class, 21 | PositiveEndpointBehaviourTests.class, 22 | NegativeServerAvailabilityTests.class 23 | }) 24 | public class GrpcTestSuites { 25 | 26 | /** 27 | * Default constructor for the {@link GrpcTestSuites} class. This constructor is empty as it 28 | * does not need to perform any initialization. 29 | */ 30 | public GrpcTestSuites() {} 31 | } 32 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/blockmessaging/BlockItemHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.blockmessaging; 3 | 4 | /** 5 | * Interface for handling block items. 6 | */ 7 | public interface BlockItemHandler { 8 | /** 9 | * Handle a list of block items. Always called on handler thread. Each registered handler will have its own virtual 10 | * thread. 11 | *

12 | * When you get block items they could be the start of a block, starting with a header or middle block items, or end 13 | * with a block proof. The first block items you as a listener receive could be any of these and might be in the 14 | * middle of a block. You may get a full complete block header to proof, or it is possible to get a half complete 15 | * block because the sender had an issue and could not send the rest of the block. So if you get a block header and 16 | * have not received the block proof, you should assume that the block is incomplete and throw away the data. 17 | * Hopefully you will get that block resent directly after or shortly later but that is not guaranteed. 18 | * 19 | * @param blockItems the immutable list of block items to handle 20 | */ 21 | void handleBlockItemsReceived(BlockItems blockItems); 22 | } 23 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/testFixtures/java/org/hiero/block/simulator/fixtures/generator/TestBlockStreamManager.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.fixtures.generator; 3 | 4 | import static org.hiero.block.simulator.fixtures.blocks.BlockBuilder.createBlocks; 5 | 6 | import com.hedera.hapi.block.stream.protoc.Block; 7 | import org.hiero.block.simulator.config.types.GenerationMode; 8 | import org.hiero.block.simulator.generator.BlockStreamManager; 9 | 10 | public class TestBlockStreamManager { 11 | 12 | public static BlockStreamManager getTestBlockStreamManager(final int blockCount) { 13 | return new BlockStreamManager() { 14 | int blockIndex = 0; 15 | 16 | @Override 17 | public GenerationMode getGenerationMode() { 18 | return null; 19 | } 20 | 21 | @Override 22 | public Block getNextBlock() { 23 | if (blockIndex < blockCount) { 24 | Block block = createBlocks(blockIndex, blockIndex + 1); 25 | blockIndex++; 26 | return block; 27 | } 28 | return null; 29 | } 30 | 31 | @Override 32 | public void resetToBlock(long block) {} 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/docker/simulator-promtail-config.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | http_listen_port: 9095 3 | grpc_listen_port: 0 4 | clients: 5 | - url: http://loki:3100/loki/api/v1/push 6 | positions: 7 | filename: /tmp/positions.yaml 8 | scrape_configs: 9 | # Docker Service Discovery 10 | - job_name: docker-logs 11 | docker_sd_configs: 12 | - host: unix:///var/run/docker.sock 13 | pipeline_stages: 14 | - docker: 15 | docker_url: unix:///var/run/docker.sock 16 | # This multiline stage merges multiple lines for one exception stack trace 17 | # into a single log message. 18 | - multiline: 19 | # firstline: A regex that identifies the start of a new log entry 20 | firstline: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}' 21 | # Maximum wait time for more lines before sending the collected log upstream 22 | max_wait_time: 3s 23 | relabel_configs: 24 | - source_labels: [__meta_docker_container_name] 25 | regex: "/(.*)" 26 | replacement: "$1" 27 | target_label: container_name 28 | - source_labels: [__meta_docker_container_image] 29 | target_label: image 30 | - source_labels: [__meta_docker_container_id] 31 | target_label: container_id 32 | - target_label: job 33 | replacement: docker-logs 34 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/data/ConsumerConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.data; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | import org.hiero.block.simulator.config.logging.Loggable; 7 | import org.hiero.block.simulator.config.types.SlowDownType; 8 | 9 | /** 10 | * Defines the configuration data for the consumer. 11 | * 12 | * @param startBlockNumber the block number from which to start consuming 13 | * @param endBlockNumber the block number at which to stop consuming 14 | * @param slowDownType the type of slowdown to apply while consuming 15 | * @param slowDownMilliseconds the slowdown in milliseconds 16 | * @param slowDownForBlockRange the range of blocks to apply the slowdown 17 | */ 18 | @ConfigData("consumer") 19 | public record ConsumerConfig( 20 | @Loggable @ConfigProperty(defaultValue = "-1") long startBlockNumber, 21 | @Loggable @ConfigProperty(defaultValue = "-1") long endBlockNumber, 22 | @Loggable @ConfigProperty(defaultValue = "NONE") SlowDownType slowDownType, 23 | @Loggable @ConfigProperty(defaultValue = "2") long slowDownMilliseconds, 24 | @Loggable @ConfigProperty(defaultValue = "10-30") String slowDownForBlockRange) {} 25 | -------------------------------------------------------------------------------- /tools-and-tests/protobuf-protoc/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | open module org.hiero.block.protobuf.protoc { 3 | exports com.hedera.hapi.services.auxiliary.hints.legacy; 4 | exports com.hedera.hapi.services.auxiliary.tss.legacy; 5 | exports com.hedera.hapi.services.auxiliary.history.legacy; 6 | exports com.hedera.hapi.node.hooks.legacy; 7 | exports com.hedera.hapi.node.state.hooks.legacy; 8 | exports com.hedera.hapi.node.state.tss.legacy; 9 | exports com.hedera.services.stream.proto; 10 | exports com.hederahashgraph.api.proto.java; 11 | exports com.hedera.hapi.block.stream.protoc; 12 | exports com.hedera.hapi.block.stream.input.protoc; 13 | exports com.hedera.hapi.block.stream.output.protoc; 14 | exports com.hedera.hapi.block.stream.trace.protoc; 15 | exports com.hedera.hapi.platform.event.legacy; 16 | exports com.hedera.hapi.platform.state.legacy; 17 | exports org.hiero.block.api.protoc; 18 | exports org.hiero.block.internal.protoc; 19 | 20 | requires transitive com.google.common; 21 | requires transitive com.google.protobuf; 22 | requires transitive io.grpc.stub; 23 | requires transitive io.grpc; 24 | requires io.grpc.protobuf; 25 | requires static com.github.spotbugs.annotations; 26 | requires static java.annotation; 27 | } 28 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/docker/update-env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script creates a '.env' file that is used for docker-compose as input for environment variables 4 | # for the simulator services. 5 | 6 | echo "Creating .env file for simulator services..." 7 | 8 | # Generate .env file with default values 9 | cat > .env << EOL 10 | GRPC_SERVER_ADDRESS=host.docker.internal 11 | PROMETHEUS_ENDPOINT_ENABLED=true 12 | 13 | # For publisher service 14 | PUBLISHER_BLOCK_STREAM_SIMULATOR_MODE=PUBLISHER_CLIENT 15 | PUBLISHER_PROMETHEUS_ENDPOINT_PORT_NUMBER=16008 16 | 17 | # For consumer service 18 | CONSUMER_BLOCK_STREAM_SIMULATOR_MODE=CONSUMER 19 | CONSUMER_PROMETHEUS_ENDPOINT_PORT_NUMBER=16009 20 | EOL 21 | 22 | logging_config_file_arg="-Djava.util.logging.config.file=/opt/hiero/block-node/logs/config/logging.properties" 23 | debug_arg="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5006" 24 | # determine if we should include debug opts 25 | [ "$1" = true ] && is_debug=true || is_debug=false 26 | if [ true = "$is_debug" ]; then 27 | # The server will wait for the debugger to attach on port 5006 28 | echo "JAVA_TOOL_OPTIONS=${logging_config_file_arg} ${debug_arg}" >> .env 29 | else 30 | echo "JAVA_TOOL_OPTIONS=${logging_config_file_arg}" >> .env 31 | fi 32 | 33 | # Output the values 34 | echo ".env properties:" 35 | cat .env 36 | echo 37 | -------------------------------------------------------------------------------- /charts/block-node-server/values-overrides/nano.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | # This override values for the block-node-server chart to deploy a mini version of the block-node-server. 4 | # This is useful for testing and development purposes with limited resources. 5 | # ie: minikube 6 | 7 | resources: 8 | requests: 9 | cpu: "500m" 10 | memory: "1Gi" 11 | limits: 12 | cpu: "1" 13 | memory: "1.5Gi" 14 | 15 | blockNode: 16 | config: 17 | JAVA_OPTS: '-Xms1G -Xmx1G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="/tmp/dump.hprof"' 18 | MESSAGING_BLOCK_ITEM_QUEUE_SIZE: "128" 19 | MESSAGING_BLOCK_NOTIFICATION_QUEUE_SIZE: "16" 20 | BACKFILL_FETCH_BATCH_SIZE: "5" 21 | persistence: 22 | archive: 23 | size: 1Gi 24 | # Optionally specify an existing PVC name instead of creating via volumeClaimTemplate 25 | existingClaim: "nano-archive-storage" 26 | live: 27 | size: 1Gi 28 | # Optionally specify an existing PVC name instead of creating via volumeClaimTemplate 29 | # existingClaim: "nano-live-pvc" 30 | logging: 31 | size: 1Gi 32 | # Optionally specify an existing PVC name instead of creating via volumeClaimTemplate 33 | # existingClaim: "nano-logging-pvc" 34 | 35 | kubepromstack: 36 | enabled: false 37 | 38 | loki: 39 | enabled: false 40 | 41 | promtail: 42 | enabled: false 43 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/generator/BlockStreamManager.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.generator; 3 | 4 | import com.hedera.hapi.block.stream.protoc.Block; 5 | import com.hedera.pbj.runtime.ParseException; 6 | import java.io.IOException; 7 | import org.hiero.block.simulator.config.types.GenerationMode; 8 | import org.hiero.block.simulator.exception.BlockSimulatorParsingException; 9 | 10 | /** The block stream manager interface. */ 11 | public interface BlockStreamManager { 12 | 13 | /** 14 | * Initialize the block stream manager and load blocks into memory. 15 | */ 16 | default void init() {} 17 | 18 | /** 19 | * Get the generation mode. 20 | * 21 | * @return the generation mode 22 | */ 23 | GenerationMode getGenerationMode(); 24 | 25 | /** 26 | * Get the next block. 27 | * 28 | * @return the next block 29 | * @throws IOException if a I/O error occurs 30 | * @throws BlockSimulatorParsingException if a parse error occurs 31 | */ 32 | Block getNextBlock() throws IOException, BlockSimulatorParsingException, ParseException; 33 | 34 | /** 35 | * Reset the block stream manager to a specific block. 36 | * 37 | * @param block the block number to reset to 38 | */ 39 | void resetToBlock(final long block); 40 | } 41 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/data/SimulatorStartupDataConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config.data; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | import java.nio.file.Path; 7 | import java.util.Objects; 8 | import org.hiero.block.simulator.config.logging.Loggable; 9 | 10 | /** 11 | * Config record for the startup data functionality. 12 | * 13 | * @param enabled whether the startup data functionality is enabled 14 | * @param latestAckBlockNumberPath path to the file containing the latest 15 | * acknowledged block number 16 | * @param latestAckBlockHashPath path to the file containing the latest 17 | */ 18 | @ConfigData("simulator.startup.data") 19 | public record SimulatorStartupDataConfig( 20 | @Loggable @ConfigProperty(defaultValue = "false") boolean enabled, 21 | @Loggable @ConfigProperty(defaultValue = "/opt/simulator/data/latestAckBlockNumber") 22 | Path latestAckBlockNumberPath, 23 | @Loggable @ConfigProperty(defaultValue = "/opt/simulator/data/latestAckBlockHash") 24 | Path latestAckBlockHashPath) { 25 | public SimulatorStartupDataConfig { 26 | Objects.requireNonNull(latestAckBlockNumberPath); 27 | Objects.requireNonNull(latestAckBlockHashPath); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/src/test/java/org/hiero/block/common/utils/StringUtilitiesTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.common.utils; 3 | 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import org.junit.jupiter.params.ParameterizedTest; 7 | import org.junit.jupiter.params.provider.MethodSource; 8 | 9 | /** 10 | * Tests for {@link StringUtilities} functionality. 11 | */ 12 | class StringUtilitiesTest { 13 | /** 14 | * This test aims to verify that the {@link StringUtilities#isBlank(String)} 15 | * returns {@code true} if the input string is blank. 16 | * 17 | * @param toTest parameterized, the String to test 18 | */ 19 | @ParameterizedTest 20 | @MethodSource("org.hiero.block.common.CommonsTestUtility#blankStrings") 21 | void testRequireNotBlankPass(final String toTest) { 22 | assertThat(StringUtilities.isBlank(toTest)).isTrue(); 23 | } 24 | 25 | /** 26 | * This test aims to verify that the {@link StringUtilities#isBlank(String)} 27 | * returns {@code false} if the input string is not blank. 28 | * 29 | * @param toTest parameterized, the string to test 30 | */ 31 | @ParameterizedTest 32 | @MethodSource("org.hiero.block.common.CommonsTestUtility#nonBlankStrings") 33 | void testRequireNotBlankFail(final String toTest) { 34 | assertThat(StringUtilities.isBlank(toTest)).isFalse(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /block-node/backfill/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.backfill.BackfillPlugin; 3 | 4 | // SPDX-License-Identifier: Apache-2.0 5 | module org.hiero.block.node.backfill { 6 | uses com.swirlds.config.api.spi.ConfigurationBuilderFactory; 7 | 8 | // export configuration classes to the config module and app 9 | exports org.hiero.block.node.backfill to 10 | com.swirlds.config.impl, 11 | com.swirlds.config.extensions, 12 | org.hiero.block.node.app; 13 | exports org.hiero.block.node.backfill.client to 14 | com.swirlds.config.extensions, 15 | com.swirlds.config.impl, 16 | org.hiero.block.node.app; 17 | 18 | requires transitive com.hedera.pbj.runtime; 19 | requires transitive com.swirlds.config.api; 20 | requires transitive com.swirlds.metrics.api; 21 | requires transitive org.hiero.block.node.spi; 22 | requires transitive org.hiero.block.protobuf.pbj; 23 | requires com.hedera.pbj.grpc.client.helidon; 24 | requires org.hiero.block.node.base; 25 | requires io.helidon.common.tls; 26 | requires io.helidon.webclient.api; 27 | requires io.helidon.webclient.grpc; 28 | requires org.antlr.antlr4.runtime; 29 | requires static transitive com.github.spotbugs.annotations; 30 | 31 | provides org.hiero.block.node.spi.BlockNodePlugin with 32 | BackfillPlugin; 33 | } 34 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/health/HealthFacility.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.health; 3 | 4 | /** 5 | * The status service is used to get the current status of the block node. 6 | */ 7 | public interface HealthFacility { 8 | /** 9 | * The status of the block node. 10 | */ 11 | enum State { 12 | /** The block node is starting up. */ 13 | STARTING, 14 | /** The block node is running. */ 15 | RUNNING, 16 | /** The block node is shutting down. */ 17 | SHUTTING_DOWN, 18 | } 19 | 20 | /** 21 | * Use this method to get the current status of the block node. 22 | * 23 | * @return the current status of the block node 24 | */ 25 | State blockNodeState(); 26 | 27 | /** 28 | * Checks if the service is running. 29 | * 30 | * @return true if the service is running, false otherwise 31 | */ 32 | default boolean isRunning() { 33 | return blockNodeState() == State.RUNNING; 34 | } 35 | 36 | /** 37 | * Shutdown the block node. This method is called to start shutting down the block node. 38 | * 39 | * @param className the name of the class stopping the service, for tracing shutdown reason 40 | * @param reason the reason for shutting down the block node 41 | */ 42 | void shutdown(final String className, final String reason); 43 | } 44 | -------------------------------------------------------------------------------- /block-node/app/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.node.spi.BlockNodePlugin; 3 | import org.hiero.block.node.spi.blockmessaging.BlockMessagingFacility; 4 | import org.hiero.block.node.spi.historicalblocks.BlockProviderPlugin; 5 | import org.hiero.block.node.spi.historicalblocks.HistoricalBlockFacility; 6 | 7 | module org.hiero.block.node.app { 8 | exports org.hiero.block.node.app; 9 | // it is expected the app module will never export any packages, only use others 10 | uses HistoricalBlockFacility; 11 | uses BlockMessagingFacility; 12 | uses BlockNodePlugin; 13 | uses BlockProviderPlugin; 14 | 15 | requires com.hedera.pbj.grpc.helidon.config; 16 | requires com.hedera.pbj.grpc.helidon; 17 | requires com.hedera.pbj.runtime; 18 | requires com.swirlds.common; 19 | requires com.swirlds.config.api; 20 | requires com.swirlds.config.extensions; 21 | requires com.swirlds.metrics.api; 22 | requires org.hiero.block.common; 23 | requires org.hiero.block.node.app.config; 24 | requires org.hiero.block.node.base; 25 | requires org.hiero.block.node.spi; 26 | requires io.helidon.common; 27 | requires io.helidon.webserver.http2; 28 | requires io.helidon.webserver; 29 | requires java.logging; // javax.annotation.processing.Generated 30 | requires static transitive com.github.spotbugs.annotations; 31 | requires static java.compiler; 32 | } 33 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/metrics/MetricsInjectionModule.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.metrics; 3 | 4 | import com.swirlds.common.metrics.platform.DefaultMetricsProvider; 5 | import com.swirlds.config.api.Configuration; 6 | import com.swirlds.metrics.api.Metrics; 7 | import dagger.Binds; 8 | import dagger.Module; 9 | import dagger.Provides; 10 | import javax.inject.Singleton; 11 | 12 | /** The module used to inject the metrics service and metrics into the application. */ 13 | @Module 14 | public interface MetricsInjectionModule { 15 | 16 | /** 17 | * Provides the metrics service. 18 | * 19 | * @param metricsService the metrics service to be used 20 | * @return the metrics service 21 | */ 22 | @Singleton 23 | @Binds 24 | MetricsService bindMetricsService(MetricsServiceImpl metricsService); 25 | 26 | /** 27 | * Provides the metrics. 28 | * 29 | * @param configuration the configuration to be used by the metrics 30 | * @return the metrics 31 | */ 32 | @Singleton 33 | @Provides 34 | static Metrics provideMetrics(Configuration configuration) { 35 | final DefaultMetricsProvider metricsProvider = new DefaultMetricsProvider(configuration); 36 | final Metrics metrics = metricsProvider.createGlobalMetrics(); 37 | metricsProvider.start(); 38 | return metrics; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/generator/itemhandler/EventHeaderHandlerTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.generator.itemhandler; 3 | 4 | import static org.junit.jupiter.api.Assertions.assertNotNull; 5 | import static org.junit.jupiter.api.Assertions.assertSame; 6 | import static org.junit.jupiter.api.Assertions.assertTrue; 7 | 8 | import com.hedera.hapi.block.stream.input.protoc.EventHeader; 9 | import com.hedera.hapi.block.stream.protoc.BlockItem; 10 | import com.hedera.hapi.platform.event.legacy.EventCore; 11 | import org.junit.jupiter.api.Test; 12 | 13 | class EventHeaderHandlerTest { 14 | 15 | @Test 16 | void testGetItem() { 17 | EventHeaderHandler handler = new EventHeaderHandler(); 18 | BlockItem item = handler.getItem(); 19 | 20 | assertNotNull(item); 21 | assertTrue(item.hasEventHeader()); 22 | 23 | EventHeader header = item.getEventHeader(); 24 | assertNotNull(header.getEventCore()); 25 | 26 | EventCore core = header.getEventCore(); 27 | assertTrue(core.getCreatorNodeId() >= 1 && core.getCreatorNodeId() < 32); 28 | } 29 | 30 | @Test 31 | void testGetItemCaching() { 32 | EventHeaderHandler handler = new EventHeaderHandler(); 33 | BlockItem item1 = handler.getItem(); 34 | BlockItem item2 = handler.getItem(); 35 | 36 | assertSame(item1, item2, "getItem should return cached instance"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /block-node/README.md: -------------------------------------------------------------------------------- 1 | # Block Node Application 2 | 3 | ## Table of Contents 4 | 5 | 1. [Overview](#overview) 6 | 2. [Prerequisites](#prerequisites) 7 | 3. [Configuration](#configuration) 8 | 4. [Metrics](#metrics) 9 | 5. [Design](#design) 10 | 1. [Block Persistence](#block-persistence) 11 | 2. [Bi-directional Producer/Consumer Streaming with gRPC](#bi-directional-producerconsumer-streaming-with-grpc) 12 | 13 | ## Overview 14 | 15 | The Block Stream Application is designed handle the output of a Hiero Node, which would be in form of Block Stream. 16 | By handling we can understand verifying, storing and applying needed state changes. 17 | It uses various configuration sources and dependency injection to manage its components. 18 | 19 | ## Configuration 20 | 21 | Refer to the [Configuration](docs/configuration.md) for configuration options. 22 | 23 | ## Quickstart 24 | 25 | Refer to the [Quickstart](docs/quickstart.md) for a quick guide on how to get started with the application. 26 | 27 | ## Metrics 28 | 29 | Refer to the [Metrics](docs/metrics.md) for metrics available in the system. 30 | 31 | ## Design 32 | 33 | ### Block Persistence 34 | 35 | Refer to the [Block Persistence](docs/design/block-persistence.md) for details on how blocks are persisted. 36 | 37 | ### Bi-directional Producer/Consumer Streaming with gRPC 38 | 39 | Refer to the [Bi-directional Producer/Consumer Streaming with gRPC](docs/design/live-streaming/bidi-producer-consumers-streaming.md) for details on how the gRPC streaming is implemented. 40 | -------------------------------------------------------------------------------- /block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/async/ScheduledBlockingExecutor.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app.fixtures.async; 3 | 4 | import edu.umd.cs.findbugs.annotations.NonNull; 5 | import java.util.concurrent.BlockingQueue; 6 | import java.util.concurrent.ScheduledThreadPoolExecutor; 7 | 8 | public class ScheduledBlockingExecutor extends ScheduledThreadPoolExecutor { 9 | /** The work queue that will be used to hold the tasks. */ 10 | private final BlockingQueue workQueue; 11 | 12 | public ScheduledBlockingExecutor(@NonNull final BlockingQueue workQueue) { 13 | super(1, Thread.ofVirtual().factory(), new AbortPolicy()); 14 | 15 | this.workQueue = workQueue; // actual work queue 16 | } 17 | 18 | public ScheduledBlockingExecutor(int corePoolSize, @NonNull final BlockingQueue workQueue) { 19 | super(corePoolSize, Thread.ofVirtual().factory(), new AbortPolicy()); 20 | 21 | this.workQueue = workQueue; // actual work queue 22 | } 23 | 24 | @Override 25 | @SuppressWarnings("all") 26 | public void execute(@NonNull final Runnable command) { 27 | try { 28 | workQueue.put(command); 29 | } catch (final InterruptedException e) { 30 | Thread.currentThread().interrupt(); 31 | throw new RuntimeException("Thread was interrupted while trying to put a task into the work queue", e); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/design/design-doc-template.md: -------------------------------------------------------------------------------- 1 | # Design Document Template 2 | 3 | ## Table of Contents 4 | 5 | 1. [Purpose](#purpose) 6 | 2. [Goals](#goals) 7 | 3. [Terms](#terms) 8 | 4. [Entities](#entities) 9 | 5. [Design](#design) 10 | 6. [Diagram](#diagram) 11 | 7. [Configuration](#configuration) 12 | 8. [Metrics](#metrics) 13 | 9. [Exceptions](#exceptions) 14 | 10. [Acceptance Tests](#acceptance-tests) 15 | 16 | ## Purpose 17 | 18 | ## Goals 19 | 20 | ## Terms 21 | 22 |

23 |
Term
24 |
A Term is any word or short phrase used in this document that 25 | requires clear definition and/or explanation.
26 |
27 | 28 | ## Entities 29 | 30 | ## Design 31 | 32 | ## Diagram 33 | 34 | Consider using mermaid to generate one or more of the following: 35 | - [User Journey](https://mermaid.js.org/syntax/userJourney.html) 36 | - [Requirement Diagram](https://mermaid.js.org/syntax/requirementDiagram.html) 37 | - [Sequence Diagram](https://mermaid.js.org/syntax/sequenceDiagram.html) 38 | - [Class Diagram](https://mermaid.js.org/syntax/classDiagram.html) 39 | - [Block Diagram](https://mermaid.js.org/syntax/block.html) 40 | - [Architecture Diagram](https://mermaid.js.org/syntax/architecture.html) 41 | - [Flowchart](https://mermaid.js.org/syntax/flowchart.html) 42 | - [State Diagram](https://mermaid.js.org/syntax/stateDiagram.html) 43 | - [Entity Relationship Diagram](https://mermaid.js.org/syntax/entityRelationshipDiagram.html)** 44 | 45 | ## Configuration 46 | 47 | ## Metrics 48 | 49 | ## Exceptions 50 | 51 | ## Acceptance Tests 52 | -------------------------------------------------------------------------------- /block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/plugintest/TestHealthFacility.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app.fixtures.plugintest; 3 | 4 | import java.lang.System.Logger.Level; 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | import org.hiero.block.node.spi.health.HealthFacility; 7 | 8 | /** 9 | * A testing {@link HealthFacility} that always returns {@link State#RUNNING} for the block node state. And fails test 10 | * if the shutdown method is called. 11 | */ 12 | public class TestHealthFacility implements HealthFacility { 13 | /** The logger for this class. */ 14 | private final System.Logger LOGGER = System.getLogger(getClass().getName()); 15 | /** Track if shutdown method was called, for tests that need to know. */ 16 | public final AtomicBoolean shutdownCalled = new AtomicBoolean(false); 17 | /** If the node is running. Can be set by tests that need it to be false */ 18 | public final AtomicBoolean isRunning = new AtomicBoolean(true); 19 | 20 | /** 21 | * {@inheritDoc} 22 | */ 23 | @Override 24 | public State blockNodeState() { 25 | return isRunning.get() ? State.RUNNING : State.SHUTTING_DOWN; 26 | } 27 | 28 | /** 29 | * {@inheritDoc} 30 | */ 31 | @Override 32 | public void shutdown(String className, String reason) { 33 | LOGGER.log(Level.ERROR, "Shutting down " + className + " " + reason); 34 | shutdownCalled.set(true); 35 | isRunning.set(false); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/blocks/MinimalBlockAccessor.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app.fixtures.blocks; 3 | 4 | import com.github.luben.zstd.Zstd; 5 | import com.hedera.hapi.block.stream.Block; 6 | import com.hedera.pbj.runtime.io.buffer.Bytes; 7 | import org.hiero.block.node.spi.historicalblocks.BlockAccessor; 8 | 9 | public final class MinimalBlockAccessor implements BlockAccessor { 10 | private final long blockNumber; 11 | private final Block block; 12 | private boolean isClosed = false; 13 | 14 | public MinimalBlockAccessor(final long blockNumber, final Block block) { 15 | this.blockNumber = blockNumber; 16 | this.block = block; 17 | } 18 | 19 | @Override 20 | public long blockNumber() { 21 | return blockNumber; 22 | } 23 | 24 | @Override 25 | public Bytes blockBytes(final Format format) { 26 | return switch (format) { 27 | case JSON -> Block.JSON.toBytes(block); 28 | case PROTOBUF -> Block.PROTOBUF.toBytes(block); 29 | case ZSTD_PROTOBUF -> zstdCompressBytes(Block.PROTOBUF.toBytes(block)); 30 | }; 31 | } 32 | 33 | private Bytes zstdCompressBytes(final Bytes bytes) { 34 | return Bytes.wrap(Zstd.compress(bytes.toByteArray())); 35 | } 36 | 37 | @Override 38 | public void close() { 39 | isClosed = true; 40 | } 41 | 42 | @Override 43 | public boolean isClosed() { 44 | return isClosed; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /block-node/backfill/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { 3 | id("org.hiero.gradle.module.library") 4 | id("com.hedera.pbj.pbj-compiler") 5 | } 6 | 7 | description = "Hiero Block Node Backfill Plugin" 8 | 9 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 10 | // and then fix the reported issues. 11 | tasks.withType().configureEach { options.compilerArgs.add("-Xlint:-exports") } 12 | 13 | tasks.javadoc { 14 | options { 15 | this as StandardJavadocDocletOptions 16 | // There are violations in the generated pbj code 17 | addStringOption("Xdoclint:-reference,-html", "-quiet") 18 | } 19 | } 20 | 21 | pbj { generateTestClasses = false } 22 | 23 | mainModuleInfo { 24 | runtimeOnly("com.swirlds.config.impl") 25 | runtimeOnly("org.apache.logging.log4j.slf4j2.impl") 26 | runtimeOnly("io.helidon.logging.jul") 27 | runtimeOnly("com.hedera.pbj.grpc.helidon.config") 28 | runtimeOnly("com.hedera.pbj.grpc.client.helidon") 29 | runtimeOnly("com.hedera.pbj.grpc.helidon") 30 | } 31 | 32 | testModuleInfo { 33 | requires("org.junit.jupiter.api") 34 | requires("org.hiero.block.node.app.test.fixtures") 35 | requires("org.mockito") 36 | } 37 | 38 | sourceSets { 39 | main { 40 | pbj { 41 | srcDir( 42 | layout.projectDirectory.dir( 43 | "src/main/java/org/hiero/block/node/backfill/client/proto" 44 | ) 45 | ) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /block-node/blocks-file-recent/src/main/java/org/hiero/block/node/blocks/files/recent/FilesRecentConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.blocks.files.recent; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | import com.swirlds.config.api.validation.annotation.Min; 7 | import java.nio.file.Path; 8 | import org.hiero.block.node.base.CompressionType; 9 | import org.hiero.block.node.base.Loggable; 10 | 11 | /** 12 | * Use this configuration across the files recent plugin. 13 | * 14 | * @param liveRootPath provides the root path for saving blocks live 15 | * @param compression compression type to use for the storage. It is assumed this never changes while a node is running 16 | * and has existing files. 17 | * @param maxFilesPerDir number of files per directory. This is used to limit the number of files in a directory to avoid 18 | * file system issues. 19 | * @param blockRetentionThreshold the retention policy threshold (count of blocks to keep). Can be positive or zero. 20 | * If set to zero, the blocks are retained indefinitely. 21 | */ 22 | @ConfigData("files.recent") 23 | public record FilesRecentConfig( 24 | @Loggable @ConfigProperty(defaultValue = "/opt/hiero/block-node/data/live") Path liveRootPath, 25 | @Loggable @ConfigProperty(defaultValue = "ZSTD") CompressionType compression, 26 | @Loggable @ConfigProperty(defaultValue = "3") int maxFilesPerDir, 27 | @Loggable @ConfigProperty(defaultValue = "96_000") @Min(0) long blockRetentionThreshold) {} 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/03-Bug-Template.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | name: Block Node Bug Report 3 | description: Create a report to help us improve 4 | projects: 5 | - "hiero-ledger/9" 6 | labels: 7 | - bug 8 | type: "Bug" 9 | body: 10 | - type: markdown 11 | attributes: 12 | value: | 13 | ## Thanks for submitting a bug report! 14 | 15 | Before submitting: 16 | 1. Try searching the existing issues and discussions to see if your issue has already been reported 17 | 2. If you're reporting a security vulnerability, please disclose responsibly via our [bug bounty program](https://hedera.com/bounty) 18 | - type: textarea 19 | id: description 20 | attributes: 21 | label: Description 22 | description: What happened and what you did you expect to happen? 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: steps 27 | attributes: 28 | label: Steps to Reproduce 29 | description: Steps to reproduce the behavior 30 | placeholder: | 31 | 1. Run the block node 32 | 2. Send a '...' request 33 | 3. Response is '...' 34 | validations: 35 | required: false 36 | - type: textarea 37 | id: context 38 | attributes: 39 | label: Additional context 40 | description: Attach any logs or screenshots relevant to the problem. 41 | placeholder: | 42 | ![Screenshot](bug.png) 43 | 44 | ```bash 45 | 2021-06-29T13:50:45.008-0600 INFO thread-1 Some logs 46 | ``` 47 | validations: 48 | required: false 49 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.gradlex.javamodule.moduleinfo.ExtraJavaModuleInfoPluginExtension 3 | 4 | plugins { 5 | id("org.hiero.gradle.build") version "0.6.3" 6 | id("com.hedera.pbj.pbj-compiler") version "0.13.1" apply false 7 | } 8 | 9 | val hieroGroup = "org.hiero.block-node" 10 | 11 | rootProject.name = "hiero-block-node" 12 | 13 | javaModules { 14 | directory(".") { group = hieroGroup } 15 | directory("tools-and-tests") { 16 | group = hieroGroup 17 | module("tools") // no 'module-info' yet 18 | } 19 | directory("block-node") { group = hieroGroup } 20 | } 21 | 22 | // @jjohannes: remove once 'swirldsVersion' is updated to '0.63.x' in 23 | // hiero-dependency-versions/build.gradle.kts 24 | @Suppress("UnstableApiUsage") 25 | gradle.lifecycle.beforeProject { 26 | plugins.withId("org.hiero.gradle.module.library") { 27 | the().apply { 28 | // rewrite requires: io.prometheus.simpleclient -> simpleclient 29 | // https://github.com/hiero-ledger/hiero-gradle-conventions/pull/178 30 | // https://github.com/hiero-ledger/hiero-consensus-node/pull/19059 31 | module("com.swirlds:swirlds-common", "com.swirlds.common") { 32 | patchRealModule() 33 | exportAllPackages() 34 | requireAllDefinedDependencies() 35 | requires("java.desktop") 36 | requires("jdk.httpserver") 37 | requires("jdk.management") 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/block-node/README.md: -------------------------------------------------------------------------------- 1 | # Server 2 | 3 | The Block Node Server Application is designed to handle the block streams output of a Hiero Consensus Node, parsing and 4 | storing the blocks and network state information. It may also, optionally, provide many value adding APIs to allow 5 | downstream applications to access block and state information. 6 | 7 | ![block-node-network-architecture](./../assets/block-node-network-architecture.svg) 8 | 9 | ## Key Technologies 10 | 11 | - **Java**: Primary programming languages. 12 | - **gRPC**: For streaming and communication. 13 | - **Protobuf**: For specification, serialization and deserialization of block data. 14 | - **Helidon**: Web server framework. 15 | - **PBJ** and **PBJ-Helidon**: protocol buffer compiler and Helidon server extension. 16 | - **Gradle**: Build and dependency management. 17 | - **LMAX Disruptor**: For high performance inter-thread messaging. 18 | - **System.Logger**: For logging. 19 | - **Zstd**, **Zip** and **tar**: For file compression at rest and archival. 20 | 21 | ## Quickstart 22 | 23 | Refer to the [Quickstart](quickstart.md) for a quick guide on how to get started with the application. 24 | 25 | ## High-Level Architecture 26 | 27 | BlockNode is a modular, event-driven network-server built on the [Helidon](https://helidon.io/) framework. 28 | The system is highly extensible, allowing developers to add and remove functionality via plugins. 29 | 30 | Additional details are captured in [Architecture Overview](architecture/architecture-overview.md). 31 | 32 | ## Configuration 33 | 34 | Refer to the [Configuration](configuration.md) for configuration options. 35 | -------------------------------------------------------------------------------- /tools-and-tests/k6/average-load/bn-server-status.js: -------------------------------------------------------------------------------- 1 | import { Client, StatusOK } from 'k6/net/grpc'; 2 | import { check, sleep } from 'k6'; 3 | import { SharedArray } from 'k6/data'; 4 | import {ServerStatusRequest} from "../lib/grpc.js"; 5 | 6 | // Configure k6 VUs scheduling and iterations & thresholds 7 | export const options = { 8 | stages: [ 9 | { duration: '2m', target: 40 }, // traffic ramp-up from 1 to 40 users (all CNs and a shadow MN) over 5 minutes. 10 | { duration: '3m', target: 100 }, // stay at 100 users for 3 minutes 11 | { duration: '1m', target: 0 }, // ramp-down to 0 users 12 | ], 13 | thresholds: { // todo make these good defaults, we need these to display tags in the result, but also to ping us if they go over 14 | 'grpc_req_duration{name:block_node_server_status}': ['p(95)<300'], 15 | }, 16 | }; 17 | 18 | // load test configuration data 19 | const data = new SharedArray('BN Test Configs', function () { 20 | return JSON.parse(open('./../data.json')).configs; 21 | })[0]; 22 | 23 | // initialize gRPC client 24 | const client = new Client(); 25 | client.load([data.protobufPath], 'block-node/api/node_service.proto'); 26 | 27 | // run test 28 | export default () => { 29 | client.connect(data.blockNodeUrl, { 30 | plaintext: true 31 | }); 32 | const params = { 33 | tags: {name: 'block_node_server_status'} 34 | }; 35 | const response = new ServerStatusRequest(client).invoke(params); 36 | check(response, { 37 | 'status is OK': (r) => r && r.status === StatusOK, 38 | }); 39 | client.close(); 40 | sleep(1); 41 | }; 42 | -------------------------------------------------------------------------------- /tools-and-tests/tools/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | # Example of the Container of block tool Blockstream for gRPC network capacity testing server mode 5 | block-tool-server: 6 | build: . 7 | image: block-tools:${VERSION} 8 | container_name: block-tools-server 9 | env_file: 10 | - .env 11 | ports: 12 | - "9090:9090" 13 | volumes: 14 | - ../resources/main/serverDefaultConfig.json:/app/conf/serverDefaultConfig.json:ro 15 | # this command starts the server mode of the networkCapacity tool 16 | command: ["networkCapacity", 17 | "-m", "server", 18 | "-c", "/app/conf/serverDefaultConfig.json", 19 | "-p", "9090"] 20 | 21 | # Example of the Container of block tool Blockstream for gRPC network capacity testing client mode 22 | block-tool-client: 23 | build: . 24 | image: block-tools:${VERSION} 25 | container_name: block-tools-client 26 | env_file: 27 | - .env 28 | depends_on: 29 | - block-tool-server 30 | volumes: 31 | - ../resources/main/clientDefaultConfig.json:/app/conf/clientDefaultConfig.json:ro 32 | # make sure to have a blockstream recording folder to use the client with 33 | - /path/to/your/recordings:/app/recording:ro 34 | # this command starts the client mode of the networkCapacity tool 35 | command: ["networkCapacity", 36 | "-m", "client", 37 | "-c", "/app/conf/clientDefaultConfig.json", 38 | "-s", "block-tool-server", 39 | "-p", "9090", 40 | "-f", "/app/recording"] 41 | 42 | -------------------------------------------------------------------------------- /charts/blockstream-simulator/values.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | image: 3 | repository: ghcr.io/hiero-ledger/hiero-block-node/simulator-image 4 | pullPolicy: IfNotPresent 5 | # Overrides the image tag whose default is the chart appVersion. 6 | tag: "" 7 | 8 | imagePullSecrets: [] 9 | nameOverride: "" 10 | fullnameOverride: "" 11 | podAnnotations: {} 12 | podSecurityContext: {} 13 | securityContext: {} 14 | resources: {} 15 | nodeSelector: {} 16 | tolerations: [] 17 | affinity: {} 18 | 19 | replicas: 1 20 | 21 | simulator: 22 | config: 23 | # either CONSUMER or PUBLISHER 24 | BLOCK_STREAM_SIMULATOR_MODE: "PUBLISHER_CLIENT" 25 | GRPC_SERVER_ADDRESS: "my-bn-block-node-helm-chart" 26 | GRPC_PORT: 40840 27 | # GENERATOR_START_BLOCK_NUMBER: 0 28 | # GENERATOR_MIN_TRANSACTIONS_PER_EVENT: 500 29 | # GENERATOR_MAX_TRANSACTIONS_PER_EVENT: 5000 30 | # BLOCK_STREAM_BLOCK_ITEMS_BATCH_SIZE: 250 31 | # BLOCK_STREAM_MILLISECONDS_PER_BLOCK: 1000 32 | SIMULATOR_STARTUP_DATA_ENABLED: "true" 33 | secret: 34 | PRIVATE_KEY: "fake_private_key" 35 | persistence: 36 | data: 37 | # If false, the chart expects an externally provided PVC 38 | create: true 39 | # Name of the externally provided PVC 40 | existingClaim: "" 41 | # Name of the subPath in the PVC to mount to mountPath in the container 42 | subPath: "simulator-data" 43 | # If create is true, the following values are used to create the PVC 44 | mountPath: "/opt/simulator/data" 45 | size: 1Gi 46 | # Optionally add a storage class name if needed 47 | # storageClass: "your-storage-class" 48 | -------------------------------------------------------------------------------- /block-node/facility-messaging/src/main/java/org/hiero/block/node/messaging/BlockItemBatchRingEvent.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.messaging; 3 | 4 | import org.hiero.block.node.spi.blockmessaging.BlockItems; 5 | 6 | /** 7 | * Simple mutable container for a BlockNotification. The ring buffer is made up of these events. 8 | */ 9 | public class BlockItemBatchRingEvent { 10 | /** The value to be published to downstream subscribers through the LMAX Disruptor. */ 11 | private BlockItems blockItems; 12 | 13 | /** Constructor for the BlockItemBatchRingEvent class. */ 14 | public BlockItemBatchRingEvent() {} 15 | 16 | /** 17 | * Sets the given value to be published to downstream subscribers through the LMAX Disruptor. 18 | * The value must not be null and the method is thread-safe. 19 | * 20 | * @param blockItems the value to set 21 | */ 22 | public void set(final BlockItems blockItems) { 23 | this.blockItems = blockItems; 24 | } 25 | 26 | /** 27 | * Gets the value of the event from the LMAX Disruptor on the consumer side. The method is 28 | * thread-safe. 29 | * 30 | * @return the value of the event 31 | */ 32 | public BlockItems get() { 33 | return blockItems; 34 | } 35 | 36 | /** 37 | * toString method to provide a string representation of the BlockItemBatchRingEvent for debugging. 38 | * 39 | * @return Debug string representation of the BlockItemBatchRingEvent 40 | */ 41 | @Override 42 | public String toString() { 43 | return "BlockItemBatchRingEvent{" + (blockItems == null ? "empty" : blockItems) + '}'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /protobuf-sources/src/main/proto/block-node/api/shared_message_types.proto: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | syntax = "proto3"; 3 | 4 | package org.hiero.block.api; 5 | 6 | option java_package = "org.hiero.block.api.protoc"; 7 | // <<>> This comment is special code for setting PBJ Compiler java package 8 | option java_multiple_files = true; 9 | 10 | import "block/stream/block_item.proto"; 11 | 12 | /** 13 | * A wrapper around a repeated BlockItem.
14 | * This message is required so that we can include ordered lists of block 15 | * items as `oneof` alternatives in streams. 16 | * 17 | * Each `BlockItemSet` MUST contain at least one `BlockItem`, 18 | * and MAY contain up to one full block.
19 | * A single `BlockItemSet` SHALL NOT contain block items from 20 | * more than one block.
21 | * If a `BlockHeader` is present in a `BlockItemSet`, that item 22 | * MUST be the first item in the list.
23 | * If a `BlockProof` is present in a `BlockItemSet`, that item 24 | * MUST be the last item in the list. 25 | */ 26 | message BlockItemSet { 27 | /** 28 | * An ordered list of `BlockItem`s.
29 | * This list supports sending block items to subscribers in batches 30 | * for greater channel efficiency. 31 | */ 32 | repeated com.hedera.hapi.block.stream.BlockItem block_items = 1; 33 | } 34 | 35 | message BlockEnd { 36 | /** 37 | * A Block Number.
38 | * This is the block number of the completed block. 39 | *

40 | * This MUST match the block number of corresponding `BlockHeader` block 41 | * item that started this block. 42 | */ 43 | uint64 block_number = 1; 44 | } 45 | -------------------------------------------------------------------------------- /docs/tools/quickstart.md: -------------------------------------------------------------------------------- 1 | # Quickstart of the Tools 2 | 3 | ## Table of Contents 4 | 5 | 1. [Running locally](#running-locally) 6 | 1. [Build the Tools](#build-the-tools) 7 | 2. [Run the Tools](#run-the-tools) 8 | 9 | ## Running locally 10 | 11 | - Tools subproject qualifier: `:tools` 12 | - Assuming your working directory is the repo root 13 | 14 | > **NOTE:** one may use the `-p` flag for `./gradlew` in order to avoid 15 | > specifying the target subproject repeatedly on each task when running 16 | > multiple tasks. When running only a single task, however, it is 17 | > recommended to use the project qualifier (i.e. `:tools:`) for 18 | > both simplicity and clarity. 19 | 20 | ### Easy way for Unix based OSs 21 | 22 | There is a command line script for building and running tool, which is located in the root of the repository. It has the 23 | nice extra feature of giving you colored console output. 24 | 25 | ```bash 26 | ./tool.sh info --help 27 | ``` 28 | 29 | ### Build the Tools 30 | 31 | > **NOTE:** if you have not done so already, it is 32 | > generally recommended to build the entire repo first: 33 | > 34 | > ```bash 35 | > ./gradlew clean build -x test 36 | > ``` 37 | 38 | 1. To quickly build the Tools sources (without running tests), do the following: 39 | 40 | ```bash 41 | ./gradlew -p tools clean build -x test 42 | ``` 43 | 44 | ### Run the Tools 45 | 46 | 1. To run the Tools, do the following: 47 | 48 | ```bash 49 | # Here is an example of running the info command with the help option, simply 50 | # replace `info --help` with the desired command and options to run the tools 51 | # quickly using the `./gradlew run` task. 52 | ./gradlew -q :tools:run --args="info --help" 53 | ``` 54 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/config/SimulatorConfigExtension.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.config; 3 | 4 | import com.google.auto.service.AutoService; 5 | import com.swirlds.common.metrics.config.MetricsConfig; 6 | import com.swirlds.common.metrics.platform.prometheus.PrometheusConfig; 7 | import com.swirlds.config.api.ConfigurationExtension; 8 | import edu.umd.cs.findbugs.annotations.NonNull; 9 | import java.util.Set; 10 | import org.hiero.block.simulator.config.data.BlockGeneratorConfig; 11 | import org.hiero.block.simulator.config.data.BlockStreamConfig; 12 | import org.hiero.block.simulator.config.data.ConsumerConfig; 13 | import org.hiero.block.simulator.config.data.GrpcConfig; 14 | import org.hiero.block.simulator.config.data.SimulatorStartupDataConfig; 15 | import org.hiero.block.simulator.config.data.UnorderedStreamConfig; 16 | 17 | /** Sets up configuration for services. */ 18 | @AutoService(ConfigurationExtension.class) 19 | public class SimulatorConfigExtension implements ConfigurationExtension { 20 | 21 | /** Explicitly defined constructor. */ 22 | public SimulatorConfigExtension() { 23 | super(); 24 | } 25 | 26 | @NonNull 27 | @Override 28 | public Set> getConfigDataTypes() { 29 | return Set.of( 30 | BlockStreamConfig.class, 31 | UnorderedStreamConfig.class, 32 | ConsumerConfig.class, 33 | GrpcConfig.class, 34 | BlockGeneratorConfig.class, 35 | SimulatorStartupDataConfig.class, 36 | MetricsConfig.class, 37 | PrometheusConfig.class); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | import org.hiero.block.simulator.config.SimulatorConfigExtension; 3 | 4 | module org.hiero.block.simulator { 5 | exports org.hiero.block.simulator.config.data; 6 | exports org.hiero.block.simulator.exception; 7 | exports org.hiero.block.simulator; 8 | exports org.hiero.block.simulator.config.types; 9 | exports org.hiero.block.simulator.config; 10 | exports org.hiero.block.simulator.grpc; 11 | exports org.hiero.block.simulator.generator; 12 | exports org.hiero.block.simulator.metrics; 13 | exports org.hiero.block.simulator.grpc.impl; 14 | exports org.hiero.block.simulator.mode; 15 | exports org.hiero.block.simulator.mode.impl; 16 | exports org.hiero.block.simulator.config.logging to 17 | com.swirlds.config.impl; 18 | exports org.hiero.block.simulator.logging; 19 | 20 | requires com.hedera.pbj.runtime; 21 | requires com.swirlds.common; 22 | requires com.swirlds.config.api; 23 | requires com.swirlds.config.extensions; 24 | requires com.swirlds.metrics.api; 25 | requires org.hiero.block.common; 26 | requires org.hiero.block.protobuf.pbj; 27 | requires org.hiero.block.protobuf.protoc; 28 | requires com.google.protobuf; 29 | requires dagger; 30 | requires io.grpc.stub; 31 | requires io.grpc; 32 | requires java.logging; 33 | requires javax.inject; 34 | requires static transitive com.github.spotbugs.annotations; 35 | requires static transitive com.google.auto.service; 36 | requires static java.compiler; // javax.annotation.processing.Generated 37 | 38 | provides com.swirlds.config.api.ConfigurationExtension with 39 | SimulatorConfigExtension; 40 | } 41 | -------------------------------------------------------------------------------- /common/src/main/java/org/hiero/block/common/utils/ChunkUtils.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.common.utils; 3 | 4 | import edu.umd.cs.findbugs.annotations.NonNull; 5 | import java.util.ArrayList; 6 | import java.util.Collection; 7 | import java.util.Collections; 8 | import java.util.List; 9 | import java.util.Objects; 10 | 11 | /** Utility class for chunking collections. */ 12 | public final class ChunkUtils { 13 | /** 14 | * Chunk a collection into a list of lists. 15 | * The resulting list will have a specified size. 16 | * 17 | * @param dataToSplit the collection to chunk, if the collection is empty, an empty list is returned. 18 | * @param chunkSize the size of each chunk 19 | * @param the type of the collection 20 | * @return a list of lists of the specified size 21 | * */ 22 | public static List> chunkify(@NonNull final Collection dataToSplit, final int chunkSize) { 23 | Objects.requireNonNull(dataToSplit); 24 | if (chunkSize <= 0) { 25 | throw new IllegalArgumentException("Chunk size must be greater than 0"); 26 | } 27 | if (dataToSplit.isEmpty()) { 28 | return Collections.emptyList(); // or throw, depends on how we want to handle 29 | } 30 | final List localCollection = List.copyOf(dataToSplit); 31 | final int localCollectionSize = localCollection.size(); 32 | 33 | List> result = new ArrayList<>(); 34 | 35 | for (int i = 0; i < localCollectionSize; i += chunkSize) { 36 | int end = Math.min(i + chunkSize, localCollectionSize); 37 | result.add(localCollection.subList(i, end)); 38 | } 39 | 40 | return result; 41 | } 42 | 43 | private ChunkUtils() {} 44 | } 45 | -------------------------------------------------------------------------------- /block-node/protobuf-pbj/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | plugins { 3 | id("org.hiero.gradle.module.library") 4 | id("com.hedera.pbj.pbj-compiler") 5 | } 6 | 7 | description = "Hiero Block Node Protobuf PBJ API" 8 | 9 | // Remove the following line to enable all 'javac' lint checks that we have turned on by default 10 | // and then fix the reported issues. 11 | tasks.withType().configureEach { 12 | options.compilerArgs.add("-Xlint:-exports,-deprecation,-removal,-dep-ann") 13 | } 14 | 15 | tasks.javadoc { 16 | options { 17 | this as StandardJavadocDocletOptions 18 | // There are violations in the generated pbj code 19 | addStringOption("Xdoclint:-reference,-html", "-quiet") 20 | } 21 | } 22 | 23 | pbj { generateTestClasses = false } 24 | 25 | sourceSets { 26 | main { 27 | pbj { 28 | // use sources from 'protobuf' module 29 | srcDir(layout.projectDirectory.dir("../../protobuf-sources/src/main/proto")) 30 | // use sources from CN repository cloned by 'protobuf' module (see task dependency) 31 | srcDir(layout.projectDirectory.dir("../../protobuf-sources/block-node-protobuf")) 32 | // exclude BN files at root level 33 | exclude("*.proto") 34 | } 35 | } 36 | } 37 | 38 | // jjohannes: remove cross-project task dependency once the following issue is addressed 39 | // https://github.com/hiero-ledger/hiero-gradle-conventions/issues/185 40 | tasks.generatePbjSource { dependsOn(":protobuf-sources:generateBlockNodeProtoArtifact") } 41 | 42 | tasks.test { 43 | // we can exclude the standard protobuf generated tests as we don't need to test them again here 44 | // this speeds up the block node project test run no end :-) 45 | exclude("**com/hedera/**") 46 | } 47 | -------------------------------------------------------------------------------- /charts/block-node-server/values-overrides/host-paths.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: PersistentVolume 4 | metadata: 5 | name: live-storage-pv 6 | namespace: 7 | spec: 8 | accessModes: 9 | - ReadWriteOnce 10 | capacity: 11 | storage: 5Gi 12 | hostPath: 13 | path: /mnt/fast-storage/live 14 | type: DirectoryOrCreate 15 | --- 16 | apiVersion: v1 17 | kind: PersistentVolumeClaim 18 | metadata: 19 | name: live-storage-pvc 20 | namespace: 21 | spec: 22 | accessModes: 23 | - ReadWriteOnce 24 | resources: 25 | requests: 26 | storage: 5Gi 27 | volumeName: live-storage-pv 28 | --- 29 | apiVersion: v1 30 | kind: PersistentVolume 31 | metadata: 32 | name: archive-storage-pv 33 | namespace: 34 | spec: 35 | accessModes: 36 | - ReadWriteOnce 37 | capacity: 38 | storage: 5Gi 39 | hostPath: 40 | path: /mnt/fast-storage/archive 41 | type: DirectoryOrCreate 42 | --- 43 | apiVersion: v1 44 | kind: PersistentVolumeClaim 45 | metadata: 46 | name: archive-storage-pvc 47 | namespace: 48 | spec: 49 | accessModes: 50 | - ReadWriteOnce 51 | resources: 52 | requests: 53 | storage: 5Gi 54 | volumeName: archive-storage-pv 55 | --- 56 | apiVersion: v1 57 | kind: PersistentVolume 58 | metadata: 59 | name: logging-storage-pv 60 | namespace: 61 | spec: 62 | accessModes: 63 | - ReadWriteOnce 64 | capacity: 65 | storage: 5Gi 66 | hostPath: 67 | path: /mnt/fast-storage/logs 68 | type: DirectoryOrCreate 69 | --- 70 | apiVersion: v1 71 | kind: PersistentVolumeClaim 72 | metadata: 73 | name: logging-storage-pvc 74 | namespace: 75 | spec: 76 | accessModes: 77 | - ReadWriteOnce 78 | resources: 79 | requests: 80 | storage: 5Gi 81 | volumeName: logging-storage-pv 82 | -------------------------------------------------------------------------------- /charts/block-node-server/values-overrides/lfh-values.yaml: -------------------------------------------------------------------------------- 1 | blockNode: 2 | config: 3 | BLOCK_NODE_EARLIEST_MANAGED_BLOCK: "100000000" 4 | MESSAGING_BLOCK_NOTIFICATION_QUEUE_SIZE: "512" 5 | logs: 6 | level: "INFO" 7 | loggingProperties: 8 | org.hiero.block.level: "FINEST" 9 | java.util.logging.ConsoleHandler.level: "FINEST" 10 | java.util.logging.FileHandler.level: "FINEST" 11 | initContainers: 12 | - name: init-storage-dirs 13 | image: docker.io/library/busybox:latest 14 | command: 15 | - sh 16 | - -c 17 | - | 18 | chown 2000:2000 /live-pvc && \ 19 | chmod 700 /live-pvc && \ 20 | chown 2000:2000 /archive-pvc && \ 21 | chmod 700 /archive-pvc && \ 22 | chown 2000:2000 /logging-pvc && \ 23 | chmod 700 /logging-pvc 24 | volumeMounts: 25 | - name: live-storage 26 | mountPath: /live-pvc 27 | - name: archive-storage 28 | mountPath: /archive-pvc 29 | - name: logging-storage 30 | mountPath: /logging-pvc 31 | persistence: 32 | live: 33 | create: false 34 | existingClaim: live-storage-pvc 35 | subPath: "" 36 | archive: 37 | create: false 38 | existingClaim: archive-storage-pvc 39 | subPath: "" 40 | logging: 41 | create: false 42 | existingClaim: logging-storage-pvc 43 | subPath: "" 44 | 45 | service: 46 | type: LoadBalancer 47 | port: 40840 48 | -------------------------------------------------------------------------------- /charts/block-node-server/templates/grafana-dashboard-configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | SPDX-License-Identifier: Apache-2.0 3 | */}} 4 | 5 | {{ if .Values.kubepromstack.enabled }} 6 | apiVersion: v1 7 | kind: ConfigMap 8 | metadata: 9 | name: block-node-dashboard-configmap 10 | labels: 11 | grafana_dashboard: "1" 12 | data: 13 | block-node-dashboard.json: {{ .Files.Get "dashboards/block-node-server.json" | quote }} 14 | node-exporter-dashboard.json: {{ .Files.Get "dashboards/node-exporter-full.json" | quote }} 15 | kubernetes-views-pods.json : {{ .Files.Get "dashboards/kubernetes-views-pods.json" | quote }} 16 | performance-metrics.json : {{ .Files.Get "dashboards/performance-metrics.json" | quote }} 17 | app-core.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/app-core.json" | quote }} 18 | backfill.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/backfill.json" | quote }} 19 | block-access-service.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/block-access-service.json" | quote }} 20 | block-node-service.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/block-node-service.json" | quote }} 21 | block-provider-files-historic.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/block-provider-files-historic.json" | quote }} 22 | block-provider-files-recent.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/block-provider-files-recent.json" | quote }} 23 | messaging-facility.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/messaging-facility.json" | quote }} 24 | stream-publisher.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/stream-publisher.json" | quote }} 25 | stream-subscriber.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/stream-subscriber.json" | quote }} 26 | verification.json : {{ .Files.Get "dashboards/Hiero-Block-Node-Plugins/verification.json" | quote }} 27 | 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/generator/GeneratorInjectionModule.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.generator; 3 | 4 | import dagger.Module; 5 | import dagger.Provides; 6 | import edu.umd.cs.findbugs.annotations.NonNull; 7 | import javax.inject.Singleton; 8 | import org.hiero.block.simulator.config.data.BlockGeneratorConfig; 9 | import org.hiero.block.simulator.config.data.UnorderedStreamConfig; 10 | import org.hiero.block.simulator.config.types.GenerationMode; 11 | import org.hiero.block.simulator.startup.SimulatorStartupData; 12 | 13 | /** The module used to inject the block stream manager. */ 14 | @Module 15 | public interface GeneratorInjectionModule { 16 | 17 | /** 18 | * Provides the block stream manager based on the configuration settings. 19 | * For DIR generation mode: 20 | * - BlockAsFileLargeDataSets 21 | * For CRAFT generation mode: 22 | * - CraftBlockStreamManager 23 | * 24 | * @param generatorConfig the block stream configuration 25 | * @param simulatorStartupData simulator startup data 26 | * @return the appropriate BlockStreamManager implementation based on configuration 27 | */ 28 | @Singleton 29 | @Provides 30 | static BlockStreamManager providesBlockStreamManager( 31 | @NonNull final BlockGeneratorConfig generatorConfig, 32 | @NonNull final SimulatorStartupData simulatorStartupData, 33 | @NonNull final UnorderedStreamConfig unorderedStreamConfig) { 34 | final GenerationMode generationMode = generatorConfig.generationMode(); 35 | return switch (generationMode) { 36 | case DIR -> new BlockAsFileLargeDataSets(generatorConfig); 37 | case CRAFT -> new CraftBlockStreamManager(generatorConfig, simulatorStartupData, unorderedStreamConfig); 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /block-node/spi-plugins/src/main/java/org/hiero/block/node/spi/blockmessaging/BlockNotificationHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.spi.blockmessaging; 3 | 4 | /** 5 | * Interface for handling block notifications. 6 | */ 7 | public interface BlockNotificationHandler { 8 | /** 9 | * Handle a block verification notification. 10 | *

11 | * This is always called on a messaging thread. 12 | * Each registered notification handler will have its own virtual thread. 13 | * 14 | * @param notification the block verification notification to handle 15 | */ 16 | default void handleVerification(VerificationNotification notification) {} 17 | 18 | /** 19 | * Handle a block persisted notification. 20 | *

21 | * This is always called on a messaging thread. 22 | * Each registered notification handler will have its own virtual thread. 23 | * 24 | * @param notification the block persisted notification to handle 25 | */ 26 | default void handlePersisted(PersistedNotification notification) {} 27 | 28 | /** 29 | * Handle a backfilled block notification. 30 | *

31 | * This is always called on a messaging thread. 32 | * Each registered notification handler will have its own virtual thread. 33 | * 34 | * @param notification the backfilled block notification to handle 35 | */ 36 | default void handleBackfilled(BackfilledBlockNotification notification) {} 37 | 38 | /** 39 | * Handle a new block known to the network notification. Always called on handler thread. Each registered handler 40 | * will have its own virtual thread. 41 | * 42 | * @param notification the new block known to the network notification to handle 43 | */ 44 | default void handleNewestBlockKnownToNetwork(NewestBlockKnownToNetworkNotification notification) {} 45 | } 46 | -------------------------------------------------------------------------------- /block-node/app/src/main/java/org/hiero/block/node/app/ServiceBuilderImpl.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app; 3 | 4 | import com.hedera.pbj.grpc.helidon.PbjRouting; 5 | import com.hedera.pbj.runtime.grpc.ServiceInterface; 6 | import edu.umd.cs.findbugs.annotations.NonNull; 7 | import io.helidon.webserver.http.HttpRouting; 8 | import io.helidon.webserver.http.HttpRouting.Builder; 9 | import io.helidon.webserver.http.HttpService; 10 | import org.hiero.block.node.spi.ServiceBuilder; 11 | 12 | /** 13 | * Default implementation of {@link ServiceBuilder}. That builds HTTP and PBJ GRPC services. 14 | *

15 | * This class is used to register services with the block node. 16 | */ 17 | public class ServiceBuilderImpl implements ServiceBuilder { 18 | /** The HTTP routing builder. */ 19 | private final HttpRouting.Builder httpRoutingBuilder = HttpRouting.builder(); 20 | /** The PBJ GRPC routing builder. */ 21 | private final PbjRouting.Builder pbjRoutingBuilder = PbjRouting.builder(); 22 | 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | @Override 27 | public void registerHttpService(String path, HttpService... service) { 28 | httpRoutingBuilder.register(path, service); 29 | } 30 | 31 | /** 32 | * {@inheritDoc} 33 | */ 34 | @Override 35 | public void registerGrpcService(@NonNull ServiceInterface service) { 36 | pbjRoutingBuilder.service(service); 37 | } 38 | 39 | /** 40 | * Returns the HTTP routing builder. 41 | * 42 | * @return the HTTP routing builder 43 | */ 44 | Builder httpRoutingBuilder() { 45 | return httpRoutingBuilder; 46 | } 47 | 48 | /** 49 | * Returns the GRPC routing builder. 50 | * 51 | * @return the GRPC routing builder 52 | */ 53 | PbjRouting.Builder grpcRoutingBuilder() { 54 | return pbjRoutingBuilder; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /.github/release.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | changelog: 3 | exclude: 4 | labels: ["wontfix", "question", "duplicate", "invalid"] 5 | categories: 6 | - title: "⭐ New Features" 7 | labels: ["New Feature"] 8 | - title: "🚀 Enhancements" 9 | labels: ["Feature Enhancement"] 10 | - title: "🐛 Bug Fixes" 11 | labels: ["Bug"] 12 | - title: "🔨 Tests" 13 | labels: ["Tests"] 14 | - title: "📝 Documentation" 15 | labels: ["Documentation", "Design"] 16 | - title: "🔒 Security" 17 | labels: ["Security"] 18 | - title: "🔧 Improvements" 19 | labels: ["Improvement"] 20 | - title: "🔥 Breaking Changes" 21 | labels: ["Breaking Change"] 22 | - title: "⬆️ Dependency Upgrades" 23 | labels: ["dependencies"] 24 | sort: "desc" 25 | transformers: 26 | - pattern: "^feat: (.*)$" 27 | target: "Feature: $1" 28 | - pattern: "^fix: (.*)$" 29 | target: "Fix: $1" 30 | - pattern: "^docs: (.*)$" 31 | target: "Docs: $1" 32 | - pattern: "^style: (.*)$" 33 | target: "Style: $1" 34 | - pattern: "^refactor: (.*)$" 35 | target: "Refactor: $1" 36 | - pattern: "^perf: (.*)$" 37 | target: "Performance: $1" 38 | - pattern: "^test: (.*)$" 39 | target: "Test: $1" 40 | - pattern: "^chore: (.*)$" 41 | target: "Chore: $1" 42 | - pattern: "^revert: (.*)$" 43 | target: "Revert: $1" 44 | - pattern: "^security: (.*)$" 45 | target: "Security: $1" 46 | - pattern: "^build: (.*)$" 47 | target: "Build: $1" 48 | - pattern: "^ci: (.*)$" 49 | target: "CI: $1" 50 | template: | 51 | # $RELEASE_TITLE 52 | 53 | **Release Date:** $RELEASE_DATE 54 | 55 | ## Changes 56 | 57 | $CHANGES 58 | 59 | ## ❤️ Contributors 60 | 61 | $CONTRIBUTORS 62 | 63 | --- 64 | 65 | ## 📜 Full Changelog 66 | 67 | [View the full changelog]($COMPARE_URL) 68 | -------------------------------------------------------------------------------- /tools-and-tests/tools/src/main/java/org/hiero/block/tools/BlockStreamTool.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.tools; 3 | 4 | import org.hiero.block.tools.commands.BlockInfo; 5 | import org.hiero.block.tools.commands.ConvertToJson; 6 | import org.hiero.block.tools.commands.NetworkCapacity; 7 | import org.hiero.block.tools.commands.record2blocks.Record2BlockCommand; 8 | import org.hiero.block.tools.commands.record2blocks.gcp.AddNewerBlockTimes; 9 | import org.hiero.block.tools.commands.record2blocks.mirrornode.ExtractBlockTimes; 10 | import org.hiero.block.tools.commands.record2blocks.mirrornode.FetchMirrorNodeRecordsCsv; 11 | import org.hiero.block.tools.commands.record2blocks.mirrornode.ValidateBlockTimes; 12 | import picocli.CommandLine; 13 | import picocli.CommandLine.Command; 14 | 15 | /** 16 | * Command line tool for working with Hedera block stream files 17 | */ 18 | @SuppressWarnings("InstantiationOfUtilityClass") 19 | @Command( 20 | name = "subcommands", 21 | mixinStandardHelpOptions = true, 22 | version = "BlockStreamTool 0.1", 23 | subcommands = { 24 | ConvertToJson.class, 25 | BlockInfo.class, 26 | Record2BlockCommand.class, 27 | FetchMirrorNodeRecordsCsv.class, 28 | ExtractBlockTimes.class, 29 | ValidateBlockTimes.class, 30 | AddNewerBlockTimes.class, 31 | NetworkCapacity.class 32 | }) 33 | public final class BlockStreamTool { 34 | 35 | /** 36 | * Empty Default constructor to remove JavaDoc warning 37 | */ 38 | public BlockStreamTool() {} 39 | 40 | /** 41 | * Main entry point for the app 42 | * @param args command line arguments 43 | */ 44 | public static void main(String... args) { 45 | int exitCode = new CommandLine(new BlockStreamTool()).execute(args); 46 | System.exit(exitCode); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/mode/PublisherServerModeHandlerTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.mode; 3 | 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | import static org.mockito.Mockito.doThrow; 6 | import static org.mockito.Mockito.verify; 7 | 8 | import org.hiero.block.simulator.grpc.PublishStreamGrpcServer; 9 | import org.hiero.block.simulator.mode.impl.PublisherServerModeHandler; 10 | import org.junit.jupiter.api.BeforeEach; 11 | import org.junit.jupiter.api.Test; 12 | import org.mockito.Mock; 13 | import org.mockito.MockitoAnnotations; 14 | 15 | public class PublisherServerModeHandlerTest { 16 | 17 | @Mock 18 | private PublishStreamGrpcServer publishStreamGrpcServer; 19 | 20 | private PublisherServerModeHandler publisherServerModeHandler; 21 | 22 | @BeforeEach 23 | void setUp() { 24 | MockitoAnnotations.openMocks(this); 25 | publisherServerModeHandler = new PublisherServerModeHandler(publishStreamGrpcServer); 26 | } 27 | 28 | @Test 29 | void testConstructorWithNullArguments() { 30 | assertThrows(NullPointerException.class, () -> new PublisherServerModeHandler(null)); 31 | } 32 | 33 | @Test 34 | void testInit() { 35 | publisherServerModeHandler.init(); 36 | verify(publishStreamGrpcServer).init(); 37 | } 38 | 39 | @Test 40 | void testStop() throws InterruptedException { 41 | publisherServerModeHandler.stop(); 42 | verify(publishStreamGrpcServer).shutdown(); 43 | } 44 | 45 | @Test 46 | void testStop_throwsException() throws InterruptedException { 47 | doThrow(new InterruptedException("Test exception")) 48 | .when(publishStreamGrpcServer) 49 | .shutdown(); 50 | 51 | assertThrows(InterruptedException.class, () -> publisherServerModeHandler.stop()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /docs/block-node/architecture/data-flow.md: -------------------------------------------------------------------------------- 1 | # BlockNode API Data Flows 2 | 3 | This document describes multiple data flows between system components using its event-driven architecture. 4 | 5 | ## Block Stream Publish API Flow 6 | 7 | ** Overview should cover block items flow, merkle tree building, verification, persistence, and notification. ** 8 | 9 | ![block-item-publish-flow](./../../assets/block-item-publish-flow.svg) 10 | 11 | Detailed Steps: 12 | 13 | 1. gRPC publisher client sends a stream of Block Items to a Block Node. 14 | 2. Block Node server receives the stream via the `BlockStreamPublishService` implemented by the `StreamPublisherPlugin`. 15 | 3. The `StreamPublisherPlugin` publishes the stream to the `BlockMessagingFacility`. 16 | - This plugin publishes Notifications when backfill is needed. 17 | 4. The `BlockMessagingFacility` broadcasts Block Items to all registered plugins (handlers). Each handler runs on a 18 | pool of threads managed by the `BlockMessagingFacility`, reducing context switching for efficient scalability. 19 | 5. `VerificationServicePlugin` process Block Items building the block merkle tree and verifying it upon receipt of a 20 | block proof. 21 | - This plugin publishes a `VerificationNotification` upon successful verification. 22 | 6. `BlockFilesRecentPlugin` listens for a `VerificationNotification` and persists a verified block accordingly. It also 23 | publishes a `PersistedNotification` upon completion. 24 | 7. StreamPublisherPlugin responds to a notifications asynchronously and sends responses back to the gRPC client 25 | - on a successful `PersistedNotification` it sends an acknowledgment. 26 | - on a failed `VerificationNotification` or failed `PersistedNotification` it sends a failure message. 27 | 28 | Note: Each plugin processes items independently making use of thread isolation 29 | 30 | ## Block Access API Flow 31 | 32 | ## Block Stream Subscription API Flow 33 | 34 | ## Backfilling Flow 35 | -------------------------------------------------------------------------------- /block-node/stream-subscriber/src/main/java/org/hiero/block/node/stream/subscriber/SubscriberConfig.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.stream.subscriber; 3 | 4 | import com.swirlds.config.api.ConfigData; 5 | import com.swirlds.config.api.ConfigProperty; 6 | import com.swirlds.config.api.validation.annotation.Min; 7 | import org.hiero.block.node.base.Loggable; 8 | 9 | /** 10 | * Use this configuration across the stream subscriber plugin. 11 | * 12 | * @param liveQueueSize The size of the queue used to transfer live batches 13 | * between the messaging and the client thread.
14 | * This value is a number of _batches_, not blocks, so generally this should 15 | * be around 100 times the number of blocks that should be pending at any 16 | * moment (i.e. a typical block is 100 batches, so to support 50 blocks this 17 | * value would be 5000). 18 | * @param maximumFutureRequest The furthest in the future a request can set the 19 | * start block for a stream. If a request specifies a start block further 20 | * than this many blocks above the latest known "live" block, the request will 21 | * be rejected. 22 | * @param minimumLiveQueueCapacity The minimum available capacity in the live queue 23 | * that the session will try to maintain. If there is less than this much 24 | * capacity available, the session will drop the oldest full blocks (at the queue head) 25 | * in the queue until at least this many batches can be added without blocking.
26 | * This value should typically be around 10% of the live queue size. 27 | */ 28 | @ConfigData("subscriber") 29 | public record SubscriberConfig( 30 | @Loggable @ConfigProperty(defaultValue = "4000") @Min(100) int liveQueueSize, 31 | @Loggable @ConfigProperty(defaultValue = "4000") @Min(10) long maximumFutureRequest, 32 | @Loggable @ConfigProperty(defaultValue = "400") @Min(10) int minimumLiveQueueCapacity) {} 33 | -------------------------------------------------------------------------------- /tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/metrics/MetricsServiceImpl.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.simulator.metrics; 3 | 4 | import com.swirlds.metrics.api.Counter; 5 | import com.swirlds.metrics.api.Metrics; 6 | import edu.umd.cs.findbugs.annotations.NonNull; 7 | import java.util.EnumMap; 8 | import javax.inject.Inject; 9 | 10 | /** 11 | * Use member variables of this class to update metric data for the Hedera Block Node. 12 | * 13 | *

Metrics are updated by calling the appropriate method on the metric object instance. For 14 | * example, to increment a counter, call {@link Counter#increment()}. 15 | */ 16 | public class MetricsServiceImpl implements MetricsService { 17 | 18 | private static final String CATEGORY = "hiero_block_node_simulator"; 19 | 20 | private final EnumMap counters = 21 | new EnumMap<>(SimulatorMetricTypes.Counter.class); 22 | 23 | /** 24 | * Create singleton instance of metrics service to be used throughout the application. 25 | * 26 | * @param metrics the metrics instance 27 | */ 28 | @Inject 29 | public MetricsServiceImpl(@NonNull final Metrics metrics) { 30 | // Initialize the counters 31 | for (SimulatorMetricTypes.Counter counter : SimulatorMetricTypes.Counter.values()) { 32 | counters.put( 33 | counter, 34 | metrics.getOrCreate(new Counter.Config(CATEGORY, counter.grafanaLabel()) 35 | .withDescription(counter.description()))); 36 | } 37 | } 38 | 39 | /** 40 | * Use this method to get a specific counter for the given metric type. 41 | * 42 | * @param key to get a specific counter 43 | * @return the counter 44 | */ 45 | @NonNull 46 | @Override 47 | public Counter get(@NonNull SimulatorMetricTypes.Counter key) { 48 | return counters.get(key); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/TestUtils.java: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | package org.hiero.block.node.app.fixtures; 3 | 4 | import com.swirlds.common.metrics.platform.DefaultMetricsProvider; 5 | import com.swirlds.config.api.ConfigurationBuilder; 6 | import com.swirlds.metrics.api.Metrics; 7 | import java.util.logging.Level; 8 | import java.util.logging.LogManager; 9 | import java.util.logging.Logger; 10 | 11 | /** 12 | * Generic Test Utilities. 13 | */ 14 | public class TestUtils { 15 | /** 16 | * Enable debug logging for the test. This is useful for debugging test failures. 17 | */ 18 | public static void enableDebugLogging() { 19 | // enable debug System.logger logging 20 | Logger rootLogger = LogManager.getLogManager().getLogger(""); 21 | rootLogger.setLevel(Level.ALL); 22 | for (var handler : rootLogger.getHandlers()) { 23 | handler.setLevel(Level.ALL); 24 | } 25 | } 26 | 27 | public static Metrics createMetrics() { 28 | final var metricsProvider = 29 | new DefaultMetricsProvider(createTestConfiguration().build()); 30 | final Metrics metrics = metricsProvider.createGlobalMetrics(); 31 | metricsProvider.start(); 32 | return metrics; 33 | } 34 | 35 | public static ConfigurationBuilder createTestConfiguration() { 36 | ConfigurationBuilder configurationBuilder = ConfigurationBuilder.create() 37 | .withConfigDataType(com.swirlds.common.metrics.config.MetricsConfig.class) 38 | .withConfigDataType(com.swirlds.common.metrics.platform.prometheus.PrometheusConfig.class) 39 | .withConfigDataType(org.hiero.block.node.app.config.ServerConfig.class) 40 | .withConfigDataType(org.hiero.block.node.app.config.node.NodeConfig.class) 41 | .withValue("prometheus.endpointEnabled", "false"); 42 | return configurationBuilder; 43 | } 44 | } 45 | --------------------------------------------------------------------------------