From d0c4b0e8505e739fc9eb28c847a0d64560ce773e Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 21 Apr 2016 11:44:16 -0600 Subject: [PATCH] Add more well-formedness checks/tests to tree. --- src/test/merkle_tests.cpp | 40 +++++++++++++++++++++++++++++ src/zcash/IncrementalMerkleTree.cpp | 10 ++++++++ 2 files changed, 50 insertions(+) diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index c98e6d703..c6b19cf2c 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -7,6 +7,8 @@ #include +#include + #include "utilstrencodings.h" #include "version.h" @@ -319,6 +321,8 @@ BOOST_AUTO_TEST_CASE(tree_test_vectors) } BOOST_AUTO_TEST_CASE( deserializeInvalid ) { + // attempt to deserialize a small tree from a serialized large tree + // (exceeds depth well-formedness check) ZCIncrementalMerkleTree newTree; for (size_t i = 0; i < 16; i++) { @@ -334,6 +338,42 @@ BOOST_AUTO_TEST_CASE( deserializeInvalid ) { BOOST_CHECK_THROW({ss >> newTreeSmall;}, std::ios_base::failure); } +BOOST_AUTO_TEST_CASE( deserializeInvalid2 ) { + // the most ancestral parent is empty + CDataStream ss( + ParseHex("0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3000100"), + SER_NETWORK, + PROTOCOL_VERSION + ); + + ZCIncrementalMerkleTree tree; + BOOST_CHECK_THROW(ss >> tree, std::ios_base::failure); +} + +BOOST_AUTO_TEST_CASE( deserializeInvalid3 ) { + // left doesn't exist but right does + CDataStream ss( + ParseHex("000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300"), + SER_NETWORK, + PROTOCOL_VERSION + ); + + ZCIncrementalMerkleTree tree; + BOOST_CHECK_THROW(ss >> tree, std::ios_base::failure); +} + +BOOST_AUTO_TEST_CASE( deserializeInvalid4 ) { + // left doesn't exist but a parent does + CDataStream ss( + ParseHex("000001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d"), + SER_NETWORK, + PROTOCOL_VERSION + ); + + ZCIncrementalMerkleTree tree; + BOOST_CHECK_THROW(ss >> tree, std::ios_base::failure); +} + BOOST_AUTO_TEST_CASE( testZeroElements ) { for (int start = 0; start < 20; start++) { ZCIncrementalMerkleTree newTree; diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index d4e87824d..0a391486a 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -61,6 +61,16 @@ void IncrementalMerkleTree::wfcheck() const { if (wasnull) { throw std::ios_base::failure("tree has non-canonical representation of parent"); } + + // Left cannot be empty when right exists. + if (!left && right) { + throw std::ios_base::failure("tree has non-canonical representation of tree"); + } + + // Left cannot be empty when parents is nonempty. + if (!left && parents.size() > 0) { + throw std::ios_base::failure("tree has non-canonical representation of tree"); + } } template