From 4b04e6a21dc49615e45519e1f16991ba9cd7583e Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 6 Dec 2018 16:07:22 +0000 Subject: [PATCH] Add basic hash tree API and implementation. --- .../bramble/api/sync/MessageId.java | 6 +++ .../bramble/api/sync/tree/LeafNode.java | 8 ++++ .../bramble/api/sync/tree/ParentNode.java | 9 +++++ .../bramble/api/sync/tree/TreeHash.java | 24 +++++++++++ .../bramble/api/sync/tree/TreeHasher.java | 8 ++++ .../bramble/api/sync/tree/TreeNode.java | 31 ++++++++++++++ .../bramble/sync/tree/TreeHasherImpl.java | 40 +++++++++++++++++++ 7 files changed, 126 insertions(+) create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/LeafNode.java create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/ParentNode.java create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeHash.java create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeHasher.java create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeNode.java create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/sync/tree/TreeHasherImpl.java diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java index 907b6e2d0..03ac0b840 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java @@ -24,6 +24,12 @@ public class MessageId extends UniqueId { public static final String BLOCK_LABEL = "org.briarproject.bramble/MESSAGE_BLOCK"; + /** + * Label for hashing two tree hashes to produce a parent. + */ + public static final String TREE_LABEL = + "org.briarproject.bramble/MESSAGE_TREE"; + public MessageId(byte[] id) { super(id); } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/LeafNode.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/LeafNode.java new file mode 100644 index 000000000..68d81d1a2 --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/LeafNode.java @@ -0,0 +1,8 @@ +package org.briarproject.bramble.api.sync.tree; + +public class LeafNode extends TreeNode { + + public LeafNode(TreeHash hash, int blockNumber) { + super(hash, 0, blockNumber, blockNumber); + } +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/ParentNode.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/ParentNode.java new file mode 100644 index 000000000..8d529bb9e --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/ParentNode.java @@ -0,0 +1,9 @@ +package org.briarproject.bramble.api.sync.tree; + +public class ParentNode extends TreeNode { + + public ParentNode(TreeHash hash, TreeNode left, TreeNode right) { + super(hash, Math.max(left.getHeight(), right.getHeight()) + 1, + left.getFirstBlockNumber(), right.getLastBlockNumber()); + } +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeHash.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeHash.java new file mode 100644 index 000000000..cfbe75b4b --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeHash.java @@ -0,0 +1,24 @@ +package org.briarproject.bramble.api.sync.tree; + +import org.briarproject.bramble.api.UniqueId; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import javax.annotation.concurrent.ThreadSafe; + +/** + * Type-safe wrapper for a byte array that uniquely identifies a sequence of + * one or more message blocks. + */ +@ThreadSafe +@NotNullByDefault +public class TreeHash extends UniqueId { + + public TreeHash(byte[] id) { + super(id); + } + + @Override + public boolean equals(Object o) { + return o instanceof TreeHash && super.equals(o); + } +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeHasher.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeHasher.java new file mode 100644 index 000000000..a52d555b0 --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeHasher.java @@ -0,0 +1,8 @@ +package org.briarproject.bramble.api.sync.tree; + +public interface TreeHasher { + + LeafNode hashBlock(int blockNumber, byte[] data); + + ParentNode mergeTrees(TreeNode left, TreeNode right); +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeNode.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeNode.java new file mode 100644 index 000000000..d5104f645 --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/tree/TreeNode.java @@ -0,0 +1,31 @@ +package org.briarproject.bramble.api.sync.tree; + +public class TreeNode { + + private final TreeHash hash; + private final int height, firstBlockNumber, lastBlockNumber; + + TreeNode(TreeHash hash, int height, int firstBlockNumber, + int lastBlockNumber) { + this.hash = hash; + this.height = height; + this.firstBlockNumber = firstBlockNumber; + this.lastBlockNumber = lastBlockNumber; + } + + public TreeHash getHash() { + return hash; + } + + public int getHeight() { + return height; + } + + public int getFirstBlockNumber() { + return firstBlockNumber; + } + + public int getLastBlockNumber() { + return lastBlockNumber; + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/tree/TreeHasherImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/tree/TreeHasherImpl.java new file mode 100644 index 000000000..3d15c2d77 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/tree/TreeHasherImpl.java @@ -0,0 +1,40 @@ +package org.briarproject.bramble.sync.tree; + +import org.briarproject.bramble.api.crypto.CryptoComponent; +import org.briarproject.bramble.api.sync.tree.LeafNode; +import org.briarproject.bramble.api.sync.tree.ParentNode; +import org.briarproject.bramble.api.sync.tree.TreeHash; +import org.briarproject.bramble.api.sync.tree.TreeHasher; +import org.briarproject.bramble.api.sync.tree.TreeNode; + +import javax.inject.Inject; + +import static org.briarproject.bramble.api.sync.Message.FORMAT_VERSION; +import static org.briarproject.bramble.api.sync.MessageId.BLOCK_LABEL; +import static org.briarproject.bramble.api.sync.MessageId.TREE_LABEL; + +class TreeHasherImpl implements TreeHasher { + + private static final byte[] FORMAT_VERSION_BYTES = + new byte[] {FORMAT_VERSION}; + + private final CryptoComponent crypto; + + @Inject + TreeHasherImpl(CryptoComponent crypto) { + this.crypto = crypto; + } + + @Override + public LeafNode hashBlock(int blockNumber, byte[] data) { + byte[] hash = crypto.hash(BLOCK_LABEL, FORMAT_VERSION_BYTES, data); + return new LeafNode(new TreeHash(hash), blockNumber); + } + + @Override + public ParentNode mergeTrees(TreeNode left, TreeNode right) { + byte[] hash = crypto.hash(TREE_LABEL, FORMAT_VERSION_BYTES, + left.getHash().getBytes(), right.getHash().getBytes()); + return new ParentNode(new TreeHash(hash), left, right); + } +}