Skip to content

Commit 413b1ac

Browse files
authored
feat(verification): Hashing refactor for 0.68.x HAPI version (#1865)
Signed-off-by: Alfredo Gutierrez Grajeda <[email protected]>
1 parent a67ac67 commit 413b1ac

File tree

36 files changed

+608
-490
lines changed

36 files changed

+608
-490
lines changed

block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/blocks/BlockUtils.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,6 @@ public static Block toBlock(BlockUnparsed block) {
5454
* Gets a SampleBlockInfo, out of the defined sample blocks enum.
5555
*/
5656
public static SampleBlockInfo getSampleBlockInfo(SAMPLE_BLOCKS sampleBlocks) throws IOException, ParseException {
57-
// JSON Option not working
58-
// Parsing is coming empty.
59-
// BlockUnparsed jsonOrigin = BlockUnparsed.JSON.parse(Bytes.wrap(BlockUtils.class
60-
// .getModule()
61-
// .getResourceAsStream("test-blocks/" + "perf-10K-1731.blk.json")
62-
// .readAllBytes()));
63-
6457
BlockUnparsed blockUnparsed;
6558
var stream = TestUtils.class.getModule().getResourceAsStream("test-blocks/" + sampleBlocks.blockName);
6659
try (final var gzipInputStream = new GZIPInputStream(stream)) {
@@ -87,16 +80,15 @@ public record SampleBlockInfo(Bytes blockRootHash, Long blockNumber, BlockUnpars
8780
* These blocks are used for testing purposes only.
8881
*/
8982
public enum SAMPLE_BLOCKS {
90-
HAPI_0_64_0_BLOCK_14(
91-
"HAPI-0-64-0/000000000000000000000000000000000014.blk.gz",
92-
"54dca69665741f13d8c956dffb3327edbe5d56e32d2bc66d6ce145a1e1b62fe61cddb74b19f17a5da9bb01933429d5e0",
93-
14),
9483
HAPI_0_66_0_BLOCK_10(
9584
"HAPI-0-66-0/000000000000000000000000000000000010.blk.gz",
96-
"8d6d9004594f10f15518a2c6a7c5d473077f2a83a874a9489095adc0d0bf6b7c9f7e49b1e5430203e7234ebfd2880de2",
97-
10);
85+
"30783030", // dummy hash
86+
10),
87+
HAPI_0_68_0_BLOCK_14(
88+
"HAPI-0-68-0/000000000000000000000000000000000014.blk.gz",
89+
"d4924fe896fd32375ced195f29238f36b50f1a04d7b0e34e00b82758a2e9cabd37c98945181788e309d2c9588830bbcb",
90+
14);
9891

99-
// VNymlmV0HxPYyVbf+zMn7b5dVuMtK8ZtbOFFoeG2L+Yc3bdLGfF6Xam7AZM0KdXg
10092
private final String blockName;
10193
private final Bytes blockHash;
10294
private final long blockNumber;

block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/blocks/SimpleTestBlockItemBuilder.java

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
import com.hedera.hapi.block.stream.BlockItem;
99
import com.hedera.hapi.block.stream.BlockItem.ItemOneOfType;
1010
import com.hedera.hapi.block.stream.BlockProof;
11+
import com.hedera.hapi.block.stream.TssSignedBlockProof;
1112
import com.hedera.hapi.block.stream.input.EventHeader;
1213
import com.hedera.hapi.block.stream.input.RoundHeader;
14+
import com.hedera.hapi.block.stream.output.BlockFooter;
1315
import com.hedera.hapi.block.stream.output.BlockHeader;
1416
import com.hedera.hapi.node.base.BlockHashAlgorithm;
1517
import com.hedera.hapi.node.base.SemanticVersion;
@@ -68,15 +70,16 @@ public static Bytes createRoundHeaderUnparsed(final long roundNumber) {
6870
}
6971

7072
public static BlockProof createBlockProof(final long blockNumber) {
71-
return new BlockProof(
72-
blockNumber,
73-
Bytes.wrap("previousBlockRootHash".getBytes()),
74-
Bytes.wrap("startOfBlockStateRootHash".getBytes()),
75-
Bytes.wrap("block_signature".getBytes()),
76-
Collections.emptyList(),
77-
new OneOf<>(
78-
BlockProof.VerificationReferenceOneOfType.VERIFICATION_KEY,
79-
Bytes.wrap("verificationKey".getBytes())));
73+
74+
TssSignedBlockProof.Builder tssBuildder =
75+
TssSignedBlockProof.newBuilder().blockSignature(Bytes.wrap("block_signature".getBytes()));
76+
77+
BlockProof blockProof = BlockProof.newBuilder()
78+
.block(blockNumber)
79+
.signedBlockProof(tssBuildder)
80+
.build();
81+
82+
return blockProof;
8083
}
8184

8285
public static Bytes createBlockProofUnparsed(final long blockNumber) {
@@ -129,6 +132,28 @@ public static BlockItemUnparsed sampleBlockHeaderUnparsed(final long blockNumber
129132
.build();
130133
}
131134

135+
public static BlockFooter createBlockFooter(final long blockNumber) {
136+
return BlockFooter.newBuilder()
137+
.previousBlockRootHash(Bytes.wrap("previous_block_root_hash".getBytes()))
138+
.rootHashOfAllBlockHashesTree(Bytes.wrap("root_hash_of_all_blocks".getBytes()))
139+
.startOfBlockStateRootHash(Bytes.wrap("start_block_state_root_hash".getBytes()))
140+
.build();
141+
}
142+
143+
public static Bytes createBlockFooterUnparsed(final long blockNumber) {
144+
return BlockFooter.PROTOBUF.toBytes(createBlockFooter(blockNumber));
145+
}
146+
147+
public static BlockItem sampleBlockFooter(final long blockNumber) {
148+
return new BlockItem(new OneOf<>(ItemOneOfType.BLOCK_FOOTER, createBlockFooter(blockNumber)));
149+
}
150+
151+
public static BlockItemUnparsed sampleBlockFooterUnparsed(final long blockNumber) {
152+
return BlockItemUnparsed.newBuilder()
153+
.blockFooter(Bytes.wrap(("block_footer_" + blockNumber).getBytes()))
154+
.build();
155+
}
156+
132157
public static BlockItem sampleRoundHeader(final long roundNumber) {
133158
return new BlockItem(new OneOf<>(ItemOneOfType.ROUND_HEADER, createRoundHeader(roundNumber)));
134159
}
@@ -137,8 +162,8 @@ public static BlockItem sampleRoundHeader(final long roundNumber) {
137162
* Create an EventHeader with no parents and no signature middle bit.
138163
*/
139164
public static BlockItem sampleLargeEventHeader() {
140-
return new BlockItem(new OneOf<>(
141-
ItemOneOfType.EVENT_HEADER, new EventHeader(EventCore.DEFAULT, Collections.emptyList(), false)));
165+
return new BlockItem(
166+
new OneOf<>(ItemOneOfType.EVENT_HEADER, new EventHeader(EventCore.DEFAULT, Collections.emptyList())));
142167
}
143168

144169
public static BlockItemUnparsed sampleRoundHeaderUnparsed(final long roundNumber) {
@@ -191,7 +216,8 @@ public static BlockItem[] createNumberOfVerySimpleBlocks(final long startBlockNu
191216
final int i = (blockNumber - (int) startBlockNumber) * 3;
192217
blockItems[i] = sampleBlockHeader(blockNumber);
193218
blockItems[i + 1] = sampleRoundHeader(blockNumber * 10L);
194-
blockItems[i + 2] = sampleBlockProof(blockNumber);
219+
blockItems[i + 2] = sampleBlockFooter(blockNumber * 10L);
220+
blockItems[i + 2] = sampleBlockProof(blockNumber); // TODO Improve proof generation
195221
}
196222
return blockItems;
197223
}
Binary file not shown.

block-node/base/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,5 @@ testModuleInfo {
2121
requires("org.mockito")
2222
requires("org.testcontainers")
2323
requires("io.minio")
24-
requires("junit")
2524
requires("org.hiero.block.protobuf.pbj")
2625
}

block-node/base/src/test/java/org/hiero/block/node/base/tar/TaredBlockIteratorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
import static org.hiero.block.node.app.fixtures.blocks.SimpleTestBlockItemBuilder.createNumberOfLargeBlocks;
55
import static org.hiero.block.node.app.fixtures.blocks.SimpleTestBlockItemBuilder.createNumberOfVerySimpleBlockAccessors;
6-
import static org.junit.Assert.assertThrows;
76
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
import static org.junit.jupiter.api.Assertions.assertThrows;
88
import static org.junit.jupiter.api.Assertions.fail;
99

1010
import com.github.luben.zstd.Zstd;

block-node/spi/src/test/java/org/hiero/block/node/spi/historicalblocks/BlockAccessorTest.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.hedera.hapi.block.stream.BlockItem;
1111
import com.hedera.hapi.block.stream.BlockItem.ItemOneOfType;
1212
import com.hedera.hapi.block.stream.BlockProof;
13+
import com.hedera.hapi.block.stream.TssSignedBlockProof;
1314
import com.hedera.hapi.block.stream.input.RoundHeader;
1415
import com.hedera.hapi.block.stream.output.BlockHeader;
1516
import com.hedera.hapi.node.base.BlockHashAlgorithm;
@@ -18,7 +19,6 @@
1819
import com.hedera.pbj.runtime.OneOf;
1920
import com.hedera.pbj.runtime.ParseException;
2021
import com.hedera.pbj.runtime.io.buffer.Bytes;
21-
import java.util.Collections;
2222
import java.util.List;
2323
import org.hiero.block.internal.BlockUnparsed;
2424
import org.hiero.block.node.spi.historicalblocks.BlockAccessor.Format;
@@ -41,15 +41,12 @@ public class BlockAccessorTest {
4141
new BlockItem(new OneOf<>(ItemOneOfType.ROUND_HEADER, new RoundHeader(827))),
4242
new BlockItem(new OneOf<>(
4343
ItemOneOfType.BLOCK_PROOF,
44-
new BlockProof(
45-
0,
46-
Bytes.wrap("previousBlockRootHash".getBytes()),
47-
Bytes.wrap("startOfBlockStateRootHash".getBytes()),
48-
Bytes.wrap("block_signature".getBytes()),
49-
Collections.emptyList(),
50-
new OneOf<>(
51-
BlockProof.VerificationReferenceOneOfType.VERIFICATION_KEY,
52-
Bytes.wrap("verificationKey".getBytes())))))));
44+
BlockProof.newBuilder()
45+
.block(0)
46+
.signedBlockProof(TssSignedBlockProof.newBuilder()
47+
.blockSignature(Bytes.wrap("signature"))
48+
.build())
49+
.build()))));
5350
private static final Bytes SAMPLE_BLOCK_PROTOBUF_BYTES = Block.PROTOBUF.toBytes(SAMPLE_BLOCK);
5451
private static final Bytes SAMPLE_BLOCK_ZSTD_PROTOBUF_BYTES =
5552
Bytes.wrap(Zstd.compress(Block.PROTOBUF.toBytes(SAMPLE_BLOCK).toByteArray()));

block-node/verification/src/main/java/org/hiero/block/node/verification/session/HapiVersionSessionFactory.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
import java.util.Objects;
66
import org.hiero.block.common.utils.Preconditions;
77
import org.hiero.block.node.spi.blockmessaging.BlockSource;
8+
import org.hiero.block.node.verification.session.impl.DummyVerificationSession;
89
import org.hiero.block.node.verification.session.impl.ExtendedMerkleTreeSession;
9-
import org.hiero.block.node.verification.session.impl.PreviewSimpleHashSession;
1010

1111
/**
1212
* Factory for creating {@link VerificationSession} instances based on the requested HAPI version.
1313
*/
1414
public final class HapiVersionSessionFactory {
15+
private static final SemanticVersion V_0_69_0 = semanticVersion(0, 69, 0);
1516
private static final SemanticVersion V_0_68_0 = semanticVersion(0, 68, 0);
1617
private static final SemanticVersion V_0_64_0 = semanticVersion(0, 64, 0);
1718

@@ -33,14 +34,22 @@ public static VerificationSession createSession(
3334
Objects.requireNonNull(hapiVersion, "hapiVersion cannot be null");
3435
Preconditions.requireWhole(blockNumber, "blockNumber must be >= 0");
3536

37+
// TODO, before going live we should remove the Dummy Implementation.
38+
if (isGreaterThanOrEqual(hapiVersion, V_0_69_0)) {
39+
return new DummyVerificationSession(blockNumber, blockSource);
40+
}
41+
3642
if (isGreaterThanOrEqual(hapiVersion, V_0_68_0)) {
37-
return new ExtendedMerkleTreeSession(blockNumber, blockSource, "extraBytesPlaceholder");
38-
} else if (isGreaterThanOrEqual(hapiVersion, V_0_64_0)) {
39-
return new PreviewSimpleHashSession(blockNumber, blockSource);
40-
} else {
41-
final String unsupportedMessage = "Unsupported HAPI version: %s (supported from 0.64.0 and up)";
42-
throw new IllegalArgumentException(unsupportedMessage.formatted(toShortString(hapiVersion)));
43+
return new ExtendedMerkleTreeSession(blockNumber, blockSource);
4344
}
45+
46+
// TODO, before going live we should remove the Dummy Implementation.
47+
if (isGreaterThanOrEqual(hapiVersion, V_0_64_0)) {
48+
return new DummyVerificationSession(blockNumber, blockSource);
49+
}
50+
51+
throw new IllegalArgumentException(
52+
"Unsupported HAPI version: %s (supported from 0.64.0 and up)".formatted(toShortString(hapiVersion)));
4453
}
4554

4655
/** v >= w ? (lexicographic by major, minor, patch) */
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
package org.hiero.block.node.verification.session.impl;
3+
4+
import static java.lang.System.Logger.Level.INFO;
5+
import static java.lang.System.Logger.Level.TRACE;
6+
7+
import com.hedera.pbj.runtime.ParseException;
8+
import com.hedera.pbj.runtime.io.buffer.Bytes;
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
import org.hiero.block.internal.BlockItemUnparsed;
12+
import org.hiero.block.internal.BlockUnparsed;
13+
import org.hiero.block.node.spi.blockmessaging.BlockSource;
14+
import org.hiero.block.node.spi.blockmessaging.VerificationNotification;
15+
import org.hiero.block.node.verification.session.VerificationSession;
16+
17+
// TODO, before going live we should remove the Dummy Implementation.
18+
/**
19+
* Dummy implementation of VerificationSession for testing purposes.
20+
* It simply collects block items and returns a successful verification notification
21+
* if the last block item has a block proof.
22+
*/
23+
public class DummyVerificationSession implements VerificationSession {
24+
private final System.Logger LOGGER = System.getLogger(getClass().getName());
25+
26+
/** The block number being verified. */
27+
protected final long blockNumber;
28+
29+
/** The source of the block, used to construct the final notification. */
30+
private final BlockSource blockSource;
31+
32+
/**
33+
* The block items for the block this session is responsible for. We collect them here so we can provide the
34+
* complete block in the final notification.
35+
*/
36+
protected final List<BlockItemUnparsed> blockItems = new ArrayList<>();
37+
38+
public DummyVerificationSession(final long blockNumber, final BlockSource blockSource) {
39+
this.blockNumber = blockNumber;
40+
this.blockSource = blockSource;
41+
LOGGER.log(INFO, "Created DummyVerificationSession for block {0}", blockNumber);
42+
}
43+
44+
@Override
45+
public VerificationNotification processBlockItems(List<BlockItemUnparsed> blockItems) throws ParseException {
46+
this.blockItems.addAll(blockItems);
47+
LOGGER.log(TRACE, "Processed {0} block items for block {1}", blockItems.size(), blockNumber);
48+
if (blockItems.getLast().hasBlockProof()) {
49+
BlockUnparsed block =
50+
BlockUnparsed.newBuilder().blockItems(this.blockItems).build();
51+
Bytes blockHash = Bytes.wrap("0x00");
52+
LOGGER.log(TRACE, "Returning always True verification notification for block {0}", blockNumber);
53+
return new VerificationNotification(true, blockNumber, blockHash, block, blockSource);
54+
}
55+
return null;
56+
}
57+
}

0 commit comments

Comments
 (0)