Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
583097f
WIP Add FlatListProof tests
dmitry-timofeev Oct 4, 2019
4b00ad3
Add tests for 2-element valid proofs
dmitry-timofeev Oct 7, 2019
b2188b4
Add todos on incomplete trees
dmitry-timofeev Oct 7, 2019
b2821c5
Add tests for trees having odd numbers of nodes on some levels
dmitry-timofeev Oct 7, 2019
6df880a
Fix the number of elements
dmitry-timofeev Oct 7, 2019
c37810b
Extend the integration test to cover various odd-numbered lists
dmitry-timofeev Oct 7, 2019
388b0a6
Add tests for empty-range proof.
dmitry-timofeev Oct 8, 2019
9a3f6b0
WIP Impl proof verification:
dmitry-timofeev Oct 9, 2019
b48cd7c
Fix duplicate elements detection
dmitry-timofeev Oct 10, 2019
a169dc6
Add a test for invalid hash entry at the top.
dmitry-timofeev Oct 10, 2019
ab577b9
Improve test for redundant hash nodes overriding the calculated one.
dmitry-timofeev Oct 10, 2019
06abb62
Migrate off multimap
dmitry-timofeev Oct 10, 2019
1731e8b
Extract newCheckedProof
dmitry-timofeev Oct 10, 2019
0bca025
Fix the checkstyle
dmitry-timofeev Oct 10, 2019
f1dc209
Refactor the verification code, improve documentation
dmitry-timofeev Oct 10, 2019
0f6e9b6
Link the article
dmitry-timofeev Oct 10, 2019
7d8e096
Disable the new IT
dmitry-timofeev Oct 10, 2019
978230e
Add a test for size checks
dmitry-timofeev Oct 10, 2019
3a461e1
Fix final
dmitry-timofeev Oct 10, 2019
e9ef8ab
Fix the HashMap with expected size instantiation:
dmitry-timofeev Oct 10, 2019
1228987
Fix unused import
dmitry-timofeev Oct 11, 2019
c023f4c
Resolve the todo
dmitry-timofeev Oct 11, 2019
8ecbff9
WIP resolve some todos
dmitry-timofeev Oct 11, 2019
cb286cb
Push #getHeight to the hashed entry:
dmitry-timofeev Oct 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* If it is valid, the proof contents may be accessed. See {@link CheckedListProof}
* and {@link CheckedMapProof} for available contents description.
*/
// todo: Why do we need to represent invalid proofs?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we throwing an exception?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The flat proof currently does not implement UncheckedProof interface, that's why it may and does throw exceptions. I decided exceptions are easier to implement and test. The question is on the original reasoning to represent them this way.

There is a year-old https://jira.bf.local/browse/ECR-2410 to reconsider.

public interface CheckedProof {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@
* }</pre>
*/
public interface CheckedListProof<E> extends CheckedProof {

/**
* Returns the size of the list: the total number of elements in it.
*/
long size();

/**
* Get all list proof elements. There might be several consecutive ranges.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ public CheckedListProofImpl(HashCode calculatedIndexHash,
this.proofStatus = checkNotNull(proofStatus);
}

@Override
public long size() {
// todo:
return 0;
}

@Override
public NavigableMap<Long, E> getElements() {
checkValid();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2019 The Exonum Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.exonum.binding.common.proofs.list;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.List;

/**
* A flat list proof. It proves that certain elements are present in a proof list
* of a certain size.
*/
class FlatListProof {
private final List<ListProofElementEntry> elements;
private final List<ListProofHashedEntry> proof;
private final long size;

FlatListProof(List<ListProofElementEntry> elements,
List<ListProofHashedEntry> proof, long size) {
this.elements = checkNotNull(elements);
this.proof = checkNotNull(proof);
this.size = size;
}

CheckedListProof<byte[]> verify() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2019 The Exonum Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.exonum.binding.common.proofs.list;

/**
* todo:
*/
public class InvalidProofException extends RuntimeException {

/**
* Constructs a new runtime exception with {@code null} as its detail message. The cause is not
* initialized, and may subsequently be initialized by a call to {@link #initCause}.
*/
public InvalidProofException() {
super();
}

/**
* Constructs a new runtime exception with the specified detail message. The cause is not
* initialized, and may subsequently be initialized by a call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for later retrieval by the
* {@link #getMessage()} method.
*/
public InvalidProofException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2019 The Exonum Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.exonum.binding.common.proofs.list;

import com.google.auto.value.AutoValue;

/**
* A value stored in the Merkle tree at its bottom level (at height 0).
*/
@AutoValue
abstract class ListProofElementEntry implements ListProofEntry {

/**
* Returns a value of the element stored at this index in the list.
*/
abstract byte[] getElement();

static ListProofElementEntry newInstance(long index, byte[] element) {
ListProofEntry.checkIndex(index);
return new AutoValue_ListProofElementEntry(index, 0, element);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2019 The Exonum Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.exonum.binding.common.proofs.list;

import static com.google.common.base.Preconditions.checkArgument;

interface ListProofEntry {

/**
* The maximum height of a list proof tree.
*/
int MAX_HEIGHT = 56;

/**
* The maximum index of a list proof node: 2^56 - 1.
*/
long MAX_INDEX = 0xFF_FFFF_FFFF_FFFFL;

/**
* Returns the index of the proof tree node at the height of its level. Indexes start
* from 0 for the leftmost node and up to <em>2^d - 1</em> for the rightmost node,
* where <em>d = ceil(log2(N)) - h</em> is the depth of the node at height <em>h</em>;
* <em>N</em> is the number of elements in the tree.
*/
long getIndex();

/**
* Returns the height of the proof tree node corresponding to this entry.
* The height of leaf nodes is equal to 0; the height of the root, or top node:
* <em>ceil(log2(N))</em>.
*/
int getHeight();

static void checkIndex(long index) {
checkArgument(0 <= index && index <= MAX_INDEX,
"Entry index (%s) is out of range [0; 2^56]", index);
}

static void checkHeight(int height) {
checkArgument(0 <= height && height <= MAX_HEIGHT,
"Entry height (%s) is out of range [0; 56]", height);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2019 The Exonum Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.exonum.binding.common.proofs.list;

import com.exonum.binding.common.hash.HashCode;
import com.google.auto.value.AutoValue;

/**
* A hash of a sub-tree in a Merkle proof tree.
*/
@AutoValue
abstract class ListProofHashedEntry implements ListProofEntry {
// todo: do we need the interface (are we going to operate on the entries using the interface?)
// Do we need entries at all, or just hashes?

/**
* Returns the hash of the sub-tree this entry represents.
*/
abstract HashCode getHash();

static ListProofHashedEntry newInstance(long index, int height, HashCode nodeHash) {
ListProofEntry.checkIndex(index);
ListProofEntry.checkHeight(height);
return new AutoValue_ListProofHashedEntry(index, height, nodeHash);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package com.exonum.binding.common.proofs.list;

/**
* A proof that some elements exist in a proof list. You must
* A proof that some elements exist in a proof list of a certain size. You must
* {@link #check} its structure and index hash before accessing the elements.
*/
public interface UncheckedListProof {
Expand Down
Loading