Skip to content

Commit ec4fd33

Browse files
authored
fix: 21882: Corner cases for merkle tree hashing (#21910)
Fixes: #21882 Reviewed-by: Anthony Petrov <[email protected]>, Ivan Malygin <[email protected]>, Joseph Sinclair <[email protected]>, Nikita Lebedev <[email protected]> Signed-off-by: Artem Ananev <[email protected]>
1 parent c0f3f9b commit ec4fd33

File tree

2 files changed

+11
-5
lines changed

2 files changed

+11
-5
lines changed

platform-sdk/swirlds-virtualmap/src/main/java/com/swirlds/virtualmap/internal/hash/VirtualHasher.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.swirlds.virtualmap.internal.Path;
1414
import edu.umd.cs.findbugs.annotations.NonNull;
1515
import edu.umd.cs.findbugs.annotations.Nullable;
16+
import java.security.MessageDigest;
1617
import java.util.Arrays;
1718
import java.util.HashMap;
1819
import java.util.Iterator;
@@ -213,7 +214,7 @@ protected boolean onExecute() {
213214
if (right == null) {
214215
final long rightPath = rankPath + i * 2 + 1;
215216
right = hashReader.apply(rightPath);
216-
if ((right == null) && (rightPath != 2)) {
217+
if (right == null) {
217218
throw new RuntimeException("Failed to load hash for path = " + rightPath);
218219
}
219220
}
@@ -233,8 +234,11 @@ protected boolean onExecute() {
233234
static Hash hash(final Hash left, final Hash right) {
234235
final WritableMessageDigest wmd = MESSAGE_DIGEST_THREAD_LOCAL.get();
235236
wmd.reset();
236-
// Unique value to make sure internal node hashes are different from leaf hashes
237-
wmd.writeByte((byte) 0x02);
237+
// Unique value to make sure internal node hashes are different from leaf hashes. This
238+
// value indicates the number of child nodes. All internal virtual nodes have 2 children
239+
// except a root node in a tree with just one element / leaf. In this and only this case,
240+
// the right hash will be set to a marker NO_PATH2_HASH hash object
241+
wmd.writeByte(right == NO_PATH2_HASH ? (byte) 0x01 : (byte) 0x02);
238242
left.getBytes().writeTo(wmd);
239243
if (right != NO_PATH2_HASH) { // use identity check rather than equals
240244
right.getBytes().writeTo(wmd);
@@ -642,6 +646,8 @@ private Hash hashInternal(
642646
}
643647

644648
public Hash emptyRootHash() {
645-
return ChunkHashTask.hash(Cryptography.NULL_HASH, Cryptography.NULL_HASH);
649+
final MessageDigest md = Cryptography.DEFAULT_DIGEST_TYPE.buildDigest();
650+
md.update((byte) 0x00);
651+
return new Hash(md.digest(), Cryptography.DEFAULT_DIGEST_TYPE);
646652
}
647653
}

platform-sdk/swirlds-virtualmap/src/test/java/com/swirlds/virtualmap/internal/hash/VirtualHasherTestBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ protected static VirtualHashRecord hashSubTree(
109109

110110
// This has to match VirtualHasher
111111
md.reset();
112-
md.update((byte) 0x02);
112+
md.update(rightHash == null ? (byte) 0x01 : (byte) 0x02);
113113
leftHash.getBytes().writeTo(md);
114114
if (rightHash != null) {
115115
rightHash.getBytes().writeTo(md);

0 commit comments

Comments
 (0)