Added CPourTx verification and construction routines.

This commit is contained in:
Sean Bowe
2015-12-30 08:22:02 -07:00
parent 69761d8269
commit 96c31d163f
4 changed files with 205 additions and 6 deletions

View File

@@ -24,8 +24,16 @@
#include <boost/assign/list_of.hpp>
#include "json/json_spirit_writer_template.h"
#include "libzerocash/ZerocashParams.h"
#include "libzerocash/IncrementalMerkleTree.h"
#include "libzerocash/PourInput.h"
#include "libzerocash/PourOutput.h"
#include "libzerocash/Address.h"
#include "libzerocash/Coin.h"
using namespace std;
using namespace json_spirit;
using namespace libzerocash;
// In script_tests.cpp
extern Array read_json(const std::string& jsondata);
@@ -285,6 +293,95 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet)
return dummyTransactions;
}
BOOST_AUTO_TEST_CASE(test_basic_pour_verification)
{
// We only check that pours are constructed properly
// and verify properly here. libsnark tends to segfault
// when our snarks or what-have-you are invalid, so
// we can't really catch everything here.
//
// See #471, #520, #459 and probably others.
//
// There may be ways to use boost tests to catch failing
// threads or processes (?) but they appear to not work
// on all platforms and would gently push us down an ugly
// path. We should just fix the assertions.
//
// Also, it's generally libzerocash's job to ensure
// the integrity of the scheme through its own tests.
static const unsigned int TEST_TREE_DEPTH = 3;
// construct the r1cs keypair
auto keypair = ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH);
ZerocashParams p(
TEST_TREE_DEPTH,
&keypair
);
// construct a merkle tree
IncrementalMerkleTree merkleTree(TEST_TREE_DEPTH);
Address addr = Address::CreateNewRandomAddress();
Coin coin(addr.getPublicAddress(), 100);
// commitment from coin
std::vector<bool> commitment(ZC_CM_SIZE * 8);
convertBytesVectorToVector(coin.getCoinCommitment().getCommitmentValue(), commitment);
// insert commitment into the merkle tree
std::vector<bool> index;
merkleTree.insertElement(commitment, index);
// compute the merkle root we will be working with
vector<unsigned char> rt(ZC_ROOT_SIZE);
{
vector<bool> root_bv(ZC_ROOT_SIZE * 8);
merkleTree.getRootValue(root_bv);
convertVectorToBytesVector(root_bv, rt);
}
merkle_authentication_path path(TEST_TREE_DEPTH);
merkleTree.getWitness(index, path);
// create CPourTx
CScript scriptPubKey;
boost::array<PourInput, 2> inputs = {
PourInput(coin, addr, convertVectorToInt(index), path),
PourInput(TEST_TREE_DEPTH) // dummy input of zero value
};
boost::array<PourOutput, 2> outputs = {
PourOutput(50),
PourOutput(50)
};
{
CPourTx pourtx(p, scriptPubKey, uint256(rt), inputs, outputs, 0, 0);
BOOST_CHECK(pourtx.Verify(p));
CDataStream ss(SER_DISK, CLIENT_VERSION);
ss << pourtx;
CPourTx pourtx_deserialized;
ss >> pourtx_deserialized;
BOOST_CHECK(pourtx_deserialized == pourtx);
BOOST_CHECK(pourtx_deserialized.Verify(p));
}
{
// Ensure that the balance equation is working.
BOOST_CHECK_THROW(CPourTx(p, scriptPubKey, uint256(rt), inputs, outputs, 10, 0), std::invalid_argument);
BOOST_CHECK_THROW(CPourTx(p, scriptPubKey, uint256(rt), inputs, outputs, 0, 10), std::invalid_argument);
}
{
// Ensure that it won't verify if the root is changed.
auto test = CPourTx(p, scriptPubKey, uint256(rt), inputs, outputs, 0, 0);
test.anchor = GetRandHash();
BOOST_CHECK(!test.Verify(p));
}
}
BOOST_AUTO_TEST_CASE(test_simple_pour_invalidity)
{
CMutableTransaction tx;