diff --git a/src/main/java/scenario/integrita/Client.java b/src/main/java/scenario/integrita/Client.java index 0156b397..c3a5b7a1 100644 --- a/src/main/java/scenario/integrita/Client.java +++ b/src/main/java/scenario/integrita/Client.java @@ -9,12 +9,13 @@ import node.BaseNode; import scenario.integrita.events.Push; import scenario.integrita.historytree.HistoryTreeNode; +import scenario.integrita.user.User; /** * Integrita client implementation. */ -public class Client implements BaseNode { +public class Client extends User implements BaseNode { UUID id; MiddleLayer network; ArrayList ids; // all ids inclding self diff --git a/src/main/java/scenario/integrita/Server.java b/src/main/java/scenario/integrita/Server.java index b33aa025..542046e1 100644 --- a/src/main/java/scenario/integrita/Server.java +++ b/src/main/java/scenario/integrita/Server.java @@ -1,42 +1,180 @@ package scenario.integrita; import java.util.ArrayList; -import java.util.HashMap; import java.util.UUID; +import groovy.lang.Tuple; import metrics.MetricsCollector; import network.MiddleLayer; import network.packets.Event; import node.BaseNode; +import scenario.integrita.database.HistoryTreeStore; import scenario.integrita.events.PushResp; import scenario.integrita.historytree.HistoryTreeNode; import scenario.integrita.historytree.NodeAddress; +import scenario.integrita.signature.Signature; +import scenario.integrita.user.User; import scenario.integrita.utils.StatusCode; /** * Integrita server implementation. */ public class Server implements BaseNode { + // Integrita related fields + int index; // server's index + int totalServers; // total number of servers + byte[] vk; // server's verification key + byte[] sk; // server's signature key + HistoryTreeStore db; + NodeAddress status; // the last node address seen by the server + + // simulator related properties UUID id; MiddleLayer network; - ArrayList ids; // all ids including self - HashMap db = new HashMap<>(); + // all UUIDs including self + ArrayList ids; + + // Constructors ------------------------------------------------------------------------- + /** + * Constructor. + */ public Server() { } + /** + * Constructor. + */ public Server(UUID selfId, MiddleLayer network) { this.id = selfId; this.network = network; } + /** + * Constructor. + */ + public Server(int index, int totalServers) { + this.index = index; + this.totalServers = totalServers; + + this.db = new HistoryTreeStore(); + + // generate signature keys + byte[][] keys = Signature.keyGen(); + this.sk = keys[0]; + this.vk = keys[1]; + } + + // getters and setters --------------------- + + public NodeAddress getStatus() { + // TODO add signature + return status; + } + + // Integrita RPCs --------------------------------------------------------------------- + + /** + * receives a HistoryTreeNode and updates its local db accordingly. + */ + public Tuple push(HistoryTreeNode historyTreeNode) { + // @TODO check the user membership via signature + + // check whether the node is submitted to the right server + int serverIndex = NodeAddress.mapServerIndex(historyTreeNode.addr, totalServers); + if (serverIndex != this.index) { + return new Tuple(new Object[]{StatusCode.Reject, null}); + } + + // the difference between the label of supplied node and the status of the server + // should be equal to the total number of servers + if (this.status != null) { + int diff = NodeAddress.toLabel(historyTreeNode.addr) - NodeAddress.toLabel(this.status); + if (diff != totalServers) { + return new Tuple(new Object[]{StatusCode.Reject, null}); + } + } + + // verify user-side signature on the leaf + // needed for the authorization + if (NodeAddress.isLeaf(historyTreeNode.addr)) { + // @TODO check the hash value + // @TODO retrieve user vk and verify the signature + byte[] vk = db.getVerificationKey(historyTreeNode.userId); + String msg = historyTreeNode.toLeaf(); + boolean res = Signature.verify(msg, historyTreeNode.signature, vk); + if (res == false) { + return new Tuple(new Object[]{StatusCode.Reject, null}); + } + } + + // verify user-side signature on the tree digest + if (NodeAddress.isTreeDigest(historyTreeNode.addr)) { + // verify signature + String msg = historyTreeNode.toLeaf(); + if (!Signature.verify(msg, historyTreeNode.signature, this.db.getVerificationKey(historyTreeNode.userId))) { + new Tuple(new Object[]{StatusCode.Reject, null}); + } + } + + // update the database just for non-temporary nodes + if (!NodeAddress.isTemporary(historyTreeNode.addr) || NodeAddress.isTreeDigest(historyTreeNode.addr)) { + db.insert(historyTreeNode); + } + + // remove tree digests of the old operations + // except the first operation + db.cleanDigests(historyTreeNode.addr); + + // update the state variable + this.status = historyTreeNode.addr; + + // server should sign tree digests + if (NodeAddress.isTreeDigest(historyTreeNode.addr)) { + String msg = historyTreeNode.toLeaf(); + byte[] signature = Signature.sign(msg, vk); + return new Tuple(new Object[]{StatusCode.Accept, signature}); + } + + // if nothing goes wrong, then the push request is done successfully + return new Tuple(new Object[]{StatusCode.Accept, null}); + } + + /** + * implements the pull algorithm based on Integrita specification. + * by this method, a user can retrieve a specific node of history tree from the server. + * The method returns a tuple, where the first item is the retrieve history tree node. + * The second item is a server-side signature in case that the retrieved node is a tree digest. + * Otherwise, the second item is null. + */ + public Tuple pull(User user, NodeAddress nodeAddress) { + // check whether user is authorized + if (!this.db.contains(user)) { + return new Tuple(new Object[]{null, null}); + } + + if (!this.db.contains(nodeAddress)) { + return new Tuple(new Object[]{null, null}); + } + + HistoryTreeNode res = this.db.get(nodeAddress); + byte[] singauture = new byte[0]; + if (NodeAddress.isTreeDigest(nodeAddress)) { + singauture = Signature.sign(res.hash, this.sk); + } + return new Tuple(new Object[]{res, singauture}); + + + } + + // BaseNode interface implementation --------------------------------------------------- + @Override public void onCreate(ArrayList allId) { this.ids = allId; this.network.ready(); } - // BaseNode interface implementation ------------ @Override public void onStart() { diff --git a/src/main/java/scenario/integrita/database/HistoryTreeStore.java b/src/main/java/scenario/integrita/database/HistoryTreeStore.java index 551beb6b..3ae683ee 100644 --- a/src/main/java/scenario/integrita/database/HistoryTreeStore.java +++ b/src/main/java/scenario/integrita/database/HistoryTreeStore.java @@ -1,7 +1,6 @@ package scenario.integrita.database; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.*; import scenario.integrita.historytree.HistoryTreeNode; import scenario.integrita.historytree.NodeAddress; @@ -12,9 +11,10 @@ */ public class HistoryTreeStore implements Store { - public HashMap users; - public HashMap historyTreeNodes; + private final HashMap users; + private final HashMap historyTreeNodes; + // constructor ---------------------------------------------- public HistoryTreeStore() { this.users = new HashMap<>(); this.historyTreeNodes = new HashMap<>(); @@ -25,24 +25,84 @@ public HistoryTreeStore(HashMap users, HashMap users) { + for (User u : users) { + this.insert(u); + } + return true; + } + + /** + * inserts all the history nodes contained in the `historyTreeNodes` into the `HistoryTreeStore` instance. + */ + public boolean insertAllNodes(ArrayList historyTreeNodes) { + for (HistoryTreeNode node : historyTreeNodes) { + this.insert(node); + } + return true; } + /** + * erases all the past nodes whose `position` precede the position of the supplied `addr` exclusively. + */ + public void cleanDigests(NodeAddress addr) { + Set keySet = historyTreeNodes.keySet(); + Iterator> it = historyTreeNodes.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + boolean isTreeDigest = NodeAddress.isTreeDigest(entry.getKey()); + if (isTreeDigest && (entry.getKey().position < addr.position) && (entry.getKey().position != 1)) { + it.remove(); + } + } + } + + // ------------------- store API ----------------- + @Override public boolean insert(HistoryTreeNode historyTreeNode) { + if (this.contains(historyTreeNode)) { + return false; + } historyTreeNodes.put(historyTreeNode.addr, historyTreeNode); return true; } @Override - public boolean insertAll(ArrayList historyTreeNodes) { - for (HistoryTreeNode node : historyTreeNodes) { - this.insert(node); - } + public boolean insert(User user) { + // TODO check duplicates + users.put(user.id, user); return true; } + @Override + public HistoryTreeNode get(NodeAddress nodeAddress) { + return historyTreeNodes.get(nodeAddress); + } + + @Override + public User get(Integer id) { + return users.get(id); + } + @Override public boolean delete(NodeAddress nodeAddress) { historyTreeNodes.remove(nodeAddress); @@ -50,15 +110,30 @@ public boolean delete(NodeAddress nodeAddress) { } @Override - public HistoryTreeNode get(NodeAddress nodeAddress) { - // if (!historyTreeNodes.containsKey(nodeAddress)) { - // return null; - // } - return historyTreeNodes.get(nodeAddress); + public boolean delete(User user) { + users.remove(user.id); + return true; } - public Integer totalNodes() { - return this.historyTreeNodes.size(); + @Override + public boolean contains(User user) { + boolean exists = this.users.containsKey(user.id); + return exists; + } + + @Override + public boolean contains(HistoryTreeNode historyTreeNode) { + boolean exists = this.historyTreeNodes.containsKey(historyTreeNode.addr); + return exists; + } + + /** + * checks if nodeAddress belongs to HistoryTreeStore object. + */ + @Override + public boolean contains(NodeAddress nodeAddress) { + boolean exists = historyTreeNodes.containsKey(nodeAddress); + return exists; } } diff --git a/src/main/java/scenario/integrita/database/Store.java b/src/main/java/scenario/integrita/database/Store.java index 95aa140e..47ace32c 100644 --- a/src/main/java/scenario/integrita/database/Store.java +++ b/src/main/java/scenario/integrita/database/Store.java @@ -1,9 +1,8 @@ package scenario.integrita.database; -import java.util.ArrayList; - import scenario.integrita.historytree.HistoryTreeNode; import scenario.integrita.historytree.NodeAddress; +import scenario.integrita.user.User; /** * storage api. @@ -12,10 +11,20 @@ public interface Store { boolean insert(HistoryTreeNode historyTreeNode); - boolean insertAll(ArrayList historyTreeNodes); + boolean insert(User user); + + HistoryTreeNode get(NodeAddress nodeAddress); + + User get(Integer id); boolean delete(NodeAddress nodeAddress); - HistoryTreeNode get(NodeAddress nodeAddress); + boolean delete(User user); + + boolean contains(User user); + + boolean contains(HistoryTreeNode historyTreeNode); + + boolean contains(NodeAddress nodeAddress); } diff --git a/src/main/java/scenario/integrita/hash/Hash.java b/src/main/java/scenario/integrita/hash/Hash.java new file mode 100644 index 00000000..4e871d94 --- /dev/null +++ b/src/main/java/scenario/integrita/hash/Hash.java @@ -0,0 +1,8 @@ +package scenario.integrita.hash; + +/** + * Hash implementation used in Merkle tree. + */ +public class Hash { + +} diff --git a/src/main/java/scenario/integrita/historytree/HistoryTreeNode.java b/src/main/java/scenario/integrita/historytree/HistoryTreeNode.java index e22c789b..5e49a90a 100644 --- a/src/main/java/scenario/integrita/historytree/HistoryTreeNode.java +++ b/src/main/java/scenario/integrita/historytree/HistoryTreeNode.java @@ -21,10 +21,8 @@ public class HistoryTreeNode { /** * constructor. * - * @param addr node address - * - * @param op type of operation - * + * @param addr node address + * @param op type of operation * @param userId the id of the author */ public HistoryTreeNode(NodeAddress addr, OperationType op, Integer userId) { @@ -46,4 +44,11 @@ public String toString() { + ", userId=" + userId + '}'; } + + /** + * returns node's hash value concatenated with its position in the tree. + */ + public String toLeaf() { + return hash + addr.position; + } } diff --git a/src/main/java/scenario/integrita/historytree/NodeAddress.java b/src/main/java/scenario/integrita/historytree/NodeAddress.java index c61c9525..9c9dc328 100644 --- a/src/main/java/scenario/integrita/historytree/NodeAddress.java +++ b/src/main/java/scenario/integrita/historytree/NodeAddress.java @@ -29,7 +29,7 @@ public static boolean isValid(NodeAddress addr) { if (addr.level < 0) { return false; } - double maxLevel = Math.ceil(Math.log(addr.position) / Math.log(2)); + double maxLevel = maxLevel(addr.position); return !(addr.level > maxLevel); } @@ -77,6 +77,11 @@ public static boolean isLeaf(NodeAddress addr) { return (addr.level == 0); } + public static int maxLevel(int position) { + int maxLev = (int) Math.ceil(Math.log(position) / Math.log(2)); + return maxLev; + } + /** * implements the L function of Integrita. * @@ -86,7 +91,7 @@ public static boolean isLeaf(NodeAddress addr) { public static int toLabel(NodeAddress addr) { int sum = 0; for (int j = 1; j < addr.position; j++) { - sum = sum + (int) Math.ceil(Math.log(j) / Math.log(2)) + 1; + sum = sum + maxLevel(j) + 1; } sum = sum + addr.level + 1; return sum; @@ -108,6 +113,7 @@ public static int mapServerIndex(NodeAddress addr, int totalNumberServer) { return index; } + //Compare only account numbers @Override public boolean equals(Object obj) { if (this == obj) { @@ -127,4 +133,6 @@ public boolean equals(Object obj) { public int hashCode() { return toLabel(this); } + + } diff --git a/src/main/java/scenario/integrita/signature/Signature.java b/src/main/java/scenario/integrita/signature/Signature.java new file mode 100644 index 00000000..873d4348 --- /dev/null +++ b/src/main/java/scenario/integrita/signature/Signature.java @@ -0,0 +1,33 @@ +package scenario.integrita.signature; + +/** + * signature implementation. + */ +public class Signature { + + /** + * generates signature and verification keys. + */ + public static byte[][] keyGen() { + // @TODO generate keys + byte[][] result = new byte[2][]; + return result; + } + + /** + * signs the message msg using provided signatureKey. + */ + public static byte[] sign(String msg, byte[] signatureKey) { + // @TODO sign using the generated keys + byte[] result = new byte[0]; + return result; + } + + /** + * verifies the signature against the supplied msg and the verificationKey. + */ + public static boolean verify(String msg, byte[] signature, byte[] verificationKey) { + // @TODO verify using the generated keys + return true; + } +} diff --git a/src/main/java/scenario/integrita/user/User.java b/src/main/java/scenario/integrita/user/User.java index d341b869..91d7a119 100644 --- a/src/main/java/scenario/integrita/user/User.java +++ b/src/main/java/scenario/integrita/user/User.java @@ -5,12 +5,18 @@ */ public class User { public Integer id; - public byte[] verificationKey; + public byte[] vk; // signature verification key + // constructors ------------------ public User(Integer id) { this.id = id; } public User() { } + + public User(Integer id, byte[] vk) { + this.id = id; + this.vk = vk; + } } diff --git a/src/test/java/scenario/integrita/ServerTest.java b/src/test/java/scenario/integrita/ServerTest.java new file mode 100644 index 00000000..ac612224 --- /dev/null +++ b/src/test/java/scenario/integrita/ServerTest.java @@ -0,0 +1,91 @@ +package scenario.integrita; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import groovy.lang.Tuple; +import org.junit.jupiter.api.Test; +import scenario.integrita.historytree.HistoryTreeNode; +import scenario.integrita.historytree.NodeAddress; +import scenario.integrita.user.User; +import scenario.integrita.utils.OperationType; +import scenario.integrita.utils.StatusCode; + +public class ServerTest { + + @Test + public void pushTestServerIndex() { + // set up a server + Server s = new Server(1, 4); + // add a user + s.db.insert(new User(1, new byte[0])); + + // create a history tree node whose index maps to the server's index + HistoryTreeNode node1 = new HistoryTreeNode(new NodeAddress(1, 0), OperationType.Insert, 1); + Tuple res = s.push(node1); + assertTrue(res.get(0) == StatusCode.Accept); + assertTrue(s.getStatus() == node1.addr); + + // create a history tree node whose address does not map to the server's index + HistoryTreeNode falsenode1 = new HistoryTreeNode(new NodeAddress(2, 0), OperationType.Insert, 1); + res = s.push(falsenode1); + assertTrue(res.get(0) == StatusCode.Reject); + assertTrue(s.getStatus() == node1.addr); + + // create a history tree node whose address is not the next expected one + HistoryTreeNode falsenode2 = new HistoryTreeNode(new NodeAddress(3, 0), OperationType.Insert, 1); + res = s.push(falsenode2); + assertTrue(res.get(0) == StatusCode.Reject); + assertTrue(s.getStatus() == node1.addr); + + // create a history tree node whose address is the next expected one + HistoryTreeNode node2 = new HistoryTreeNode(new NodeAddress(3, 1), OperationType.Insert, 1); + res = s.push(node2); + assertTrue(res.get(0) == StatusCode.Accept); + assertTrue(s.db.totalNodes() == 1); // the temporary node should not be stored + assertTrue(s.getStatus() == node2.addr); + + // TODO unit test for signature verification + + // add next node, it is a tree digest + HistoryTreeNode node3 = new HistoryTreeNode(new NodeAddress(4, 2), OperationType.Insert, 1); + res = s.push(node3); + assertTrue(res.get(0) == StatusCode.Accept); + assertTrue(s.db.totalNodes() == 2); // the temporary node should not be stored + // TODO check server signature on tree digests + assertTrue(s.getStatus() == node3.addr); + + // add next node + // this is a tree digest, so prior tree digests should get erased + HistoryTreeNode node4 = new HistoryTreeNode(new NodeAddress(5, 3), OperationType.Insert, 1); + res = s.push(node4); + assertTrue(res.get(0) == StatusCode.Accept); + assertTrue(s.db.totalNodes() == 2); // the temporary node should not be stored + assertFalse(s.db.contains(node3.addr)); // the previous tree digest should be erased + // TODO check server signature on tree digests + assertTrue(s.getStatus() == node4.addr); + } + + @Test + public void pullTest() { + // set up a server + Server s = new Server(1, 4); + // add a user + User user1 = new User(1, new byte[0]); + s.db.insert(user1); + + // create a history tree node whose index maps to the server's index + NodeAddress nodeAddress1 = new NodeAddress(1, 0); + HistoryTreeNode node1 = new HistoryTreeNode(nodeAddress1, OperationType.Insert, 1); + Tuple pushRes = s.push(node1); + assertTrue(pushRes.get(0) == StatusCode.Accept); + assertTrue(s.getStatus() == node1.addr); + + + Tuple pullRes = s.pull(user1, nodeAddress1); + assertTrue(pullRes.get(0) == node1); + assertTrue(pullRes.get(1) != null); + + + } +} diff --git a/src/test/java/scenario/integrita/database/HisoryTreeStoreTest.java b/src/test/java/scenario/integrita/database/HisoryTreeStoreTest.java index 34cfb338..3c49af2d 100644 --- a/src/test/java/scenario/integrita/database/HisoryTreeStoreTest.java +++ b/src/test/java/scenario/integrita/database/HisoryTreeStoreTest.java @@ -1,5 +1,6 @@ package scenario.integrita.database; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; @@ -13,31 +14,108 @@ public class HisoryTreeStoreTest { + /** + * populates a HistoryTreeStore with all the nodes of a history tree at its vth version + * + * @param v + * @return + */ + public HistoryTreeStore initHistoryTreeStore(int v) { + HistoryTreeStore historyTreeStore = new HistoryTreeStore(); + for (int p = 1; p <= v; p++) { + for (int l = 0; l <= NodeAddress.maxLevel(p); l++) { + HistoryTreeNode historyTreeNode = new HistoryTreeNode(new NodeAddress(p, l), OperationType.Insert, 1); + historyTreeStore.insert(historyTreeNode); + } + } + return historyTreeStore; + + } + @Test - public void TestInsertDeleteGet() { + public void TestHistoryNodes() { HistoryTreeStore historyTreeStore = new HistoryTreeStore(); // add 3 users - historyTreeStore.users.put( 1, new User(1)); - historyTreeStore.users.put( 2, new User(2)); - historyTreeStore.users.put( 2, new User(2)); + historyTreeStore.insert(new User(1)); + historyTreeStore.insert(new User(2)); + historyTreeStore.insert(new User(3)); // create three nodes, two of which have the same address - HistoryTreeNode historyTreeNode1 = new HistoryTreeNode(new NodeAddress(0, 1), OperationType.Insert, 1); + HistoryTreeNode historyTreeNode1 = new HistoryTreeNode(new NodeAddress(0, 1), OperationType.Delete, 1); // historyTreeNode2 points to the same address as historyTreeNode1 HistoryTreeNode historyTreeNode2 = new HistoryTreeNode(new NodeAddress(0, 1), OperationType.Insert, 2); HistoryTreeNode historyTreeNode3 = new HistoryTreeNode(new NodeAddress(2, 1), OperationType.Insert, 2); - historyTreeStore.insertAll(new ArrayList(Arrays.asList(historyTreeNode1, historyTreeNode2, historyTreeNode3))); + historyTreeStore.insertAllNodes(new ArrayList(Arrays.asList(historyTreeNode1, historyTreeNode2, historyTreeNode3))); + + // test get method + // insertion of historyTreeNode1 should get through but not historyTreeNode2 + assertTrue(historyTreeStore.get(historyTreeNode1.addr) == historyTreeNode1); // duplicates are not allowed assertTrue((historyTreeStore.totalNodes() == 2)); + // test contains method + assertTrue(historyTreeStore.contains(historyTreeNode1)); + assertTrue(historyTreeStore.contains(historyTreeNode3)); + historyTreeStore.delete(historyTreeNode1.addr); // check the correct deletion assertTrue((historyTreeStore.totalNodes() == 1)); // only historyTreeNode3 is left - assertTrue((historyTreeStore.get(historyTreeNode3.addr) == historyTreeNode3)); + assertTrue(historyTreeStore.contains(historyTreeNode3)); + + // test get method + assertTrue(historyTreeStore.get(historyTreeNode3.addr) == historyTreeNode3); + } + + @Test + public void TestUsers() { + HistoryTreeStore historyTreeStore = new HistoryTreeStore(); + + // add 3 users + User u1 = new User(1); + User u2 = new User(2); + User u3 = new User(3); + historyTreeStore.insertAllUsers(new ArrayList(Arrays.asList(u1, u1, u2, u3))); + + + // check whether the inserted users are correctly included + // insertion of historyTreeNode1 should get through but not historyTreeNode2 + assertTrue(historyTreeStore.get(u1.id) == u1); + assertTrue(historyTreeStore.get(u2.id) == u2); + assertTrue(historyTreeStore.get(u3.id) == u3); + + // duplicates are not allowed + assertTrue((historyTreeStore.totalUsers() == 3)); + + // test contains method + assertTrue(historyTreeStore.contains(u1)); + assertTrue(historyTreeStore.contains(u2)); + + // test delete + historyTreeStore.delete(u3); + // check the correct deletion + assertFalse(historyTreeStore.contains(u3)); + } + + @Test + public void testCleanTreeDigest() { + HistoryTreeStore historyTreeStore = initHistoryTreeStore(5); + // check the inclusion of all the tree digests up to version 5 of the tree + assertTrue(historyTreeStore.contains(new NodeAddress(1, 0))); + assertTrue(historyTreeStore.contains(new NodeAddress(2, NodeAddress.maxLevel(2)))); + assertTrue(historyTreeStore.contains(new NodeAddress(3, NodeAddress.maxLevel(3)))); + assertTrue(historyTreeStore.contains(new NodeAddress(4, NodeAddress.maxLevel(4)))); + assertTrue(historyTreeStore.contains(new NodeAddress(5, NodeAddress.maxLevel(5)))); + historyTreeStore.cleanDigests(new NodeAddress(4, 0)); + // tree digests of 2nd, and 3rd operations should be deleted + assertTrue(historyTreeStore.contains(new NodeAddress(1, 0))); + assertFalse(historyTreeStore.contains(new NodeAddress(2, NodeAddress.maxLevel(2)))); + assertFalse(historyTreeStore.contains(new NodeAddress(3, NodeAddress.maxLevel(3)))); + assertTrue(historyTreeStore.contains(new NodeAddress(4, NodeAddress.maxLevel(4)))); + assertTrue(historyTreeStore.contains(new NodeAddress(5, NodeAddress.maxLevel(5)))); } } diff --git a/src/test/java/scenario/integrita/historytree/NodeAddressTest.java b/src/test/java/scenario/integrita/historytree/NodeAddressTest.java new file mode 100644 index 00000000..2fec8071 --- /dev/null +++ b/src/test/java/scenario/integrita/historytree/NodeAddressTest.java @@ -0,0 +1,24 @@ +package scenario.integrita.historytree; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + + +public class NodeAddressTest { + @Test + public void toLabelTest() { + assertTrue(NodeAddress.toLabel(new NodeAddress(1, 0)) == 1); + + assertTrue(NodeAddress.toLabel(new NodeAddress(2, 0)) == 2); + assertTrue(NodeAddress.toLabel(new NodeAddress(2, 1)) == 3); + + assertTrue(NodeAddress.toLabel(new NodeAddress(3, 0)) == 4); + assertTrue(NodeAddress.toLabel(new NodeAddress(3, 1)) == 5); + assertTrue(NodeAddress.toLabel(new NodeAddress(3, 2)) == 6); + + assertTrue(NodeAddress.toLabel(new NodeAddress(4, 0)) == 7); + assertTrue(NodeAddress.toLabel(new NodeAddress(4, 1)) == 8); + assertTrue(NodeAddress.toLabel(new NodeAddress(4, 2)) == 9); + } +} diff --git a/src/test/java/scenario/integrita/signature/SignatureTest.java b/src/test/java/scenario/integrita/signature/SignatureTest.java new file mode 100644 index 00000000..45f32cce --- /dev/null +++ b/src/test/java/scenario/integrita/signature/SignatureTest.java @@ -0,0 +1,19 @@ +package scenario.integrita.signature; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class SignatureTest { + + @Test + public void correctnessTest() { + byte[][] keys = Signature.keyGen(); + String msg = "test message"; + byte[] sign = Signature.sign(msg,keys[0]); + boolean verification = Signature.verify(msg,sign,keys[1]); + assertTrue(verification); + } + +}