Transplant of libzcash.

This commit is contained in:
Sean Bowe
2016-05-04 18:26:21 -06:00
parent 2140639309
commit 2dc3599271
13 changed files with 212 additions and 237 deletions

View File

@@ -52,7 +52,7 @@
using namespace std; using namespace std;
libzerocash::ZerocashParams *pzerocashParams = NULL; ZCJoinSplit* pzcashParams = NULL;
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
CWallet* pwalletMain = NULL; CWallet* pwalletMain = NULL;
@@ -605,24 +605,18 @@ static void ZC_LoadParams()
boost::filesystem::path pk_path = ZC_GetParamsDir() / "zc-testnet-public-alpha-proving.key"; boost::filesystem::path pk_path = ZC_GetParamsDir() / "zc-testnet-public-alpha-proving.key";
boost::filesystem::path vk_path = ZC_GetParamsDir() / "zc-testnet-public-alpha-verification.key"; boost::filesystem::path vk_path = ZC_GetParamsDir() / "zc-testnet-public-alpha-verification.key";
libzerocash::ZerocashParams::zerocash_pp::init_public_params(); pzcashParams = ZCJoinSplit::Unopened();
LogPrintf("Loading verification key from %s\n", vk_path.string().c_str()); LogPrintf("Loading verification key from %s\n", vk_path.string().c_str());
gettimeofday(&tv_start, 0); gettimeofday(&tv_start, 0);
auto vk_loaded = libzerocash::ZerocashParams::LoadVerificationKeyFromFile(
vk_path.string(), pzcashParams->loadVerifyingKey(vk_path.string());
INCREMENTAL_MERKLE_TREE_DEPTH
);
gettimeofday(&tv_end, 0); gettimeofday(&tv_end, 0);
elapsed = float(tv_end.tv_sec-tv_start.tv_sec) + (tv_end.tv_usec-tv_start.tv_usec)/float(1000000); elapsed = float(tv_end.tv_sec-tv_start.tv_sec) + (tv_end.tv_usec-tv_start.tv_usec)/float(1000000);
LogPrintf("Loaded verification key in %fs seconds.\n", elapsed); LogPrintf("Loaded verification key in %fs seconds.\n", elapsed);
pzerocashParams = new libzerocash::ZerocashParams( pzcashParams->setProvingKeyPath(pk_path.string());
INCREMENTAL_MERKLE_TREE_DEPTH,
pk_path.string(),
&vk_loaded
);
} }
/** Initialize bitcoin. /** Initialize bitcoin.

View File

@@ -8,7 +8,7 @@
#include <string> #include <string>
#include "zerocash/ZerocashParams.h" #include "zcash/JoinSplit.hpp"
class CScheduler; class CScheduler;
class CWallet; class CWallet;
@@ -19,7 +19,7 @@ class thread_group;
} // namespace boost } // namespace boost
extern CWallet* pwalletMain; extern CWallet* pwalletMain;
extern libzerocash::ZerocashParams* pzerocashParams; extern ZCJoinSplit* pzcashParams;
void StartShutdown(); void StartShutdown();
bool ShutdownRequested(); bool ShutdownRequested();

View File

@@ -963,7 +963,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
// TODO: #808 // TODO: #808
uint256 pubKeyHash; uint256 pubKeyHash;
if (!pour.Verify(*pzerocashParams, pubKeyHash)) { if (!pour.Verify(*pzcashParams, pubKeyHash)) {
return state.DoS(100, error("CheckTransaction(): pour does not verify"), return state.DoS(100, error("CheckTransaction(): pour does not verify"),
REJECT_INVALID, "bad-txns-pour-verification-failed"); REJECT_INVALID, "bad-txns-pour-verification-failed");
} }

View File

@@ -9,72 +9,56 @@
#include "tinyformat.h" #include "tinyformat.h"
#include "utilstrencodings.h" #include "utilstrencodings.h"
#include "zerocash/PourProver.h" CPourTx::CPourTx(ZCJoinSplit& params,
#include "zerocash/PourTransaction.h"
template<std::size_t N>
boost::array<std::vector<unsigned char>, N> uint256_to_array(const boost::array<uint256, N>& in) {
boost::array<std::vector<unsigned char>, N> result;
for (size_t i = 0; i < N; i++) {
result[i] = std::vector<unsigned char>(in[i].begin(), in[i].end());
}
return result;
}
template<std::size_t N>
boost::array<uint256, N> unsigned_char_vector_array_to_uint256_array(const boost::array<std::vector<unsigned char>, N>& in) {
boost::array<uint256, N> result;
for (size_t i = 0; i < N; i++) {
result[i] = uint256(in[i]);
}
return result;
}
CPourTx::CPourTx(ZerocashParams& params,
const uint256& pubKeyHash, const uint256& pubKeyHash,
const uint256& anchor, const uint256& anchor,
const boost::array<PourInput, ZC_NUM_JS_INPUTS>& inputs, const boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
const boost::array<PourOutput, ZC_NUM_JS_OUTPUTS>& outputs, const boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
CAmount vpub_old, CAmount vpub_old,
CAmount vpub_new) : vpub_old(vpub_old), vpub_new(vpub_new), anchor(anchor) CAmount vpub_new) : vpub_old(vpub_old), vpub_new(vpub_new), anchor(anchor)
{ {
PourTransaction pourtx(params, boost::array<libzcash::Note, ZC_NUM_JS_OUTPUTS> notes;
std::vector<unsigned char>(pubKeyHash.begin(), pubKeyHash.end()),
std::vector<unsigned char>(anchor.begin(), anchor.end()),
std::vector<PourInput>(inputs.begin(), inputs.end()),
std::vector<PourOutput>(outputs.begin(), outputs.end()),
vpub_old,
vpub_new);
boost::array<std::vector<unsigned char>, ZC_NUM_JS_INPUTS> serials_bv; params.loadProvingKey();
boost::array<std::vector<unsigned char>, ZC_NUM_JS_OUTPUTS> commitments_bv; proof = params.prove(
boost::array<std::vector<unsigned char>, ZC_NUM_JS_INPUTS> macs_bv; inputs,
outputs,
proof = pourtx.unpack(serials_bv, commitments_bv, macs_bv, ciphertexts, ephemeralKey); notes,
serials = unsigned_char_vector_array_to_uint256_array(serials_bv); ciphertexts,
commitments = unsigned_char_vector_array_to_uint256_array(commitments_bv); ephemeralKey,
macs = unsigned_char_vector_array_to_uint256_array(macs_bv); pubKeyHash,
randomSeed,
macs,
serials,
commitments,
vpub_old,
vpub_new,
anchor
);
} }
bool CPourTx::Verify( bool CPourTx::Verify(
ZerocashParams& params, ZCJoinSplit& params,
const uint256& pubKeyHash const uint256& pubKeyHash
) const { ) const {
return PourProver::VerifyProof( return params.verify(
params, proof,
std::vector<unsigned char>(pubKeyHash.begin(), pubKeyHash.end()), pubKeyHash,
std::vector<unsigned char>(anchor.begin(), anchor.end()), randomSeed,
macs,
serials,
commitments,
vpub_old, vpub_old,
vpub_new, vpub_new,
uint256_to_array<ZC_NUM_JS_INPUTS>(serials), anchor
uint256_to_array<ZC_NUM_JS_OUTPUTS>(commitments),
uint256_to_array<ZC_NUM_JS_INPUTS>(macs),
proof
); );
} }
uint256 CPourTx::h_sig(ZCJoinSplit& params, const uint256& pubKeyHash) const
{
return params.h_sig(randomSeed, serials, pubKeyHash);
}
std::string COutPoint::ToString() const std::string COutPoint::ToString() const
{ {
return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n); return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n);

View File

@@ -13,14 +13,9 @@
#include <boost/array.hpp> #include <boost/array.hpp>
#include "zerocash/ZerocashParams.h"
#include "zerocash/PourInput.h"
#include "zerocash/PourOutput.h"
#include "zcash/NoteEncryption.hpp" #include "zcash/NoteEncryption.hpp"
#include "zcash/Zcash.h" #include "zcash/Zcash.h"
#include "zcash/JoinSplit.hpp"
using namespace libzerocash;
class CPourTx class CPourTx
{ {
@@ -72,17 +67,20 @@ public:
CPourTx(): vpub_old(0), vpub_new(0) { } CPourTx(): vpub_old(0), vpub_new(0) { }
CPourTx(ZerocashParams& params, CPourTx(ZCJoinSplit& params,
const uint256& pubKeyHash, const uint256& pubKeyHash,
const uint256& rt, const uint256& rt,
const boost::array<PourInput, ZC_NUM_JS_INPUTS>& inputs, const boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
const boost::array<PourOutput, ZC_NUM_JS_OUTPUTS>& outputs, const boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
CAmount vpub_old, CAmount vpub_old,
CAmount vpub_new CAmount vpub_new
); );
// Verifies that the pour proof is correct. // Verifies that the pour proof is correct.
bool Verify(ZerocashParams& params, const uint256& pubKeyHash) const; bool Verify(ZCJoinSplit& params, const uint256& pubKeyHash) const;
// Returns the calculated h_sig
uint256 h_sig(ZCJoinSplit& params, const uint256& pubKeyHash) const;
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;

View File

@@ -126,7 +126,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
// TODO: #808 // TODO: #808
uint256 pubKeyHash; uint256 pubKeyHash;
pour.push_back(Pair("valid", pourtx.Verify(*pzerocashParams, pubKeyHash))); pour.push_back(Pair("valid", pourtx.Verify(*pzcashParams, pubKeyHash)));
vpour.push_back(pour); vpour.push_back(pour);
} }

View File

@@ -166,10 +166,12 @@ BOOST_AUTO_TEST_CASE(serials_test)
void appendRandomCommitment(ZCIncrementalMerkleTree &tree) void appendRandomCommitment(ZCIncrementalMerkleTree &tree)
{ {
Address addr = Address::CreateNewRandomAddress(); libzcash::SpendingKey k = libzcash::SpendingKey::random();
Coin coin(addr.getPublicAddress(), 100); libzcash::PaymentAddress addr = k.address();
tree.append(uint256(coin.getCoinCommitment().getCommitmentValue())); libzcash::Note note(addr.a_pk, 0, uint256(), uint256());
tree.append(note.cm());
} }
BOOST_AUTO_TEST_CASE(anchors_flush_test) BOOST_AUTO_TEST_CASE(anchors_flush_test)

View File

@@ -25,7 +25,7 @@
CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h
CWallet* pwalletMain; CWallet* pwalletMain;
libzerocash::ZerocashParams *pzerocashParams; ZCJoinSplit *pzcashParams;
extern bool fPrintToConsole; extern bool fPrintToConsole;
extern void noui_connect(); extern void noui_connect();

View File

@@ -25,15 +25,11 @@
#include <boost/assign/list_of.hpp> #include <boost/assign/list_of.hpp>
#include "json/json_spirit_writer_template.h" #include "json/json_spirit_writer_template.h"
#include "zerocash/ZerocashParams.h" #include "zcash/Note.hpp"
#include "zerocash/PourInput.h" #include "zcash/Address.hpp"
#include "zerocash/PourOutput.h"
#include "zerocash/Address.h"
#include "zerocash/Coin.h"
using namespace std; using namespace std;
using namespace json_spirit; using namespace json_spirit;
using namespace libzerocash;
// In script_tests.cpp // In script_tests.cpp
extern Array read_json(const std::string& jsondata); extern Array read_json(const std::string& jsondata);
@@ -311,19 +307,18 @@ BOOST_AUTO_TEST_CASE(test_basic_pour_verification)
// the integrity of the scheme through its own tests. // the integrity of the scheme through its own tests.
// construct the r1cs keypair // construct the r1cs keypair
auto keypair = ZerocashParams::GenerateNewKeyPair(INCREMENTAL_MERKLE_TREE_DEPTH); auto p = ZCJoinSplit::Generate();
ZerocashParams p(
INCREMENTAL_MERKLE_TREE_DEPTH,
&keypair
);
// construct a merkle tree // construct a merkle tree
ZCIncrementalMerkleTree merkleTree; ZCIncrementalMerkleTree merkleTree;
Address addr = Address::CreateNewRandomAddress();
Coin coin(addr.getPublicAddress(), 100); libzcash::SpendingKey k = libzcash::SpendingKey::random();
libzcash::PaymentAddress addr = k.address();
libzcash::Note note(addr.a_pk, 100, uint256(), uint256());
// commitment from coin // commitment from coin
uint256 commitment(coin.getCoinCommitment().getCommitmentValue()); uint256 commitment = note.cm();
// insert commitment into the merkle tree // insert commitment into the merkle tree
merkleTree.append(commitment); merkleTree.append(commitment);
@@ -332,22 +327,21 @@ BOOST_AUTO_TEST_CASE(test_basic_pour_verification)
uint256 rt = merkleTree.root(); uint256 rt = merkleTree.root();
auto witness = merkleTree.witness(); auto witness = merkleTree.witness();
auto path = witness.path();
// create CPourTx // create CPourTx
uint256 pubKeyHash; uint256 pubKeyHash;
boost::array<PourInput, ZC_NUM_JS_INPUTS> inputs = { boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
PourInput(coin, addr, path), libzcash::JSInput(witness, note, k),
PourInput(INCREMENTAL_MERKLE_TREE_DEPTH) // dummy input of zero value libzcash::JSInput() // dummy input of zero value
}; };
boost::array<PourOutput, ZC_NUM_JS_OUTPUTS> outputs = { boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs = {
PourOutput(50), libzcash::JSOutput(addr, 50),
PourOutput(50) libzcash::JSOutput(addr, 50)
}; };
{ {
CPourTx pourtx(p, pubKeyHash, uint256(rt), inputs, outputs, 0, 0); CPourTx pourtx(*p, pubKeyHash, rt, inputs, outputs, 0, 0);
BOOST_CHECK(pourtx.Verify(p, pubKeyHash)); BOOST_CHECK(pourtx.Verify(*p, pubKeyHash));
CDataStream ss(SER_DISK, CLIENT_VERSION); CDataStream ss(SER_DISK, CLIENT_VERSION);
ss << pourtx; ss << pourtx;
@@ -356,21 +350,23 @@ BOOST_AUTO_TEST_CASE(test_basic_pour_verification)
ss >> pourtx_deserialized; ss >> pourtx_deserialized;
BOOST_CHECK(pourtx_deserialized == pourtx); BOOST_CHECK(pourtx_deserialized == pourtx);
BOOST_CHECK(pourtx_deserialized.Verify(p, pubKeyHash)); BOOST_CHECK(pourtx_deserialized.Verify(*p, pubKeyHash));
} }
{ {
// Ensure that the balance equation is working. // Ensure that the balance equation is working.
BOOST_CHECK_THROW(CPourTx(p, pubKeyHash, uint256(rt), inputs, outputs, 10, 0), std::invalid_argument); BOOST_CHECK_THROW(CPourTx(*p, pubKeyHash, rt, inputs, outputs, 10, 0), std::invalid_argument);
BOOST_CHECK_THROW(CPourTx(p, pubKeyHash, uint256(rt), inputs, outputs, 0, 10), std::invalid_argument); BOOST_CHECK_THROW(CPourTx(*p, pubKeyHash, rt, inputs, outputs, 0, 10), std::invalid_argument);
} }
{ {
// Ensure that it won't verify if the root is changed. // Ensure that it won't verify if the root is changed.
auto test = CPourTx(p, pubKeyHash, uint256(rt), inputs, outputs, 0, 0); auto test = CPourTx(*p, pubKeyHash, rt, inputs, outputs, 0, 0);
test.anchor = GetRandHash(); test.anchor = GetRandHash();
BOOST_CHECK(!test.Verify(p, pubKeyHash)); BOOST_CHECK(!test.Verify(*p, pubKeyHash));
} }
delete p;
} }
BOOST_AUTO_TEST_CASE(test_simple_pour_invalidity) BOOST_AUTO_TEST_CASE(test_simple_pour_invalidity)

View File

@@ -29,6 +29,8 @@
using namespace std; using namespace std;
using namespace json_spirit; using namespace json_spirit;
using namespace libzcash;
int64_t nWalletUnlockTime; int64_t nWalletUnlockTime;
static CCriticalSection cs_nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime;
@@ -2385,7 +2387,7 @@ Value zc_benchmark(const json_spirit::Array& params, bool fHelp)
if (benchmarktype == "createjoinsplit") { if (benchmarktype == "createjoinsplit") {
/* Load the proving now key so that it doesn't happen as part of the /* Load the proving now key so that it doesn't happen as part of the
* first joinsplit. */ * first joinsplit. */
pzerocashParams->loadProvingKey(); pzcashParams->loadProvingKey();
} }
for (int i = 0; i < samplecount; i++) { for (int i = 0; i < samplecount; i++) {
@@ -2454,14 +2456,12 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
LOCK(cs_main); LOCK(cs_main);
uint256 a_sk; SpendingKey k;
uint256 sk_enc;
{ {
CDataStream ssData(ParseHexV(params[0], "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION); CDataStream ssData(ParseHexV(params[0], "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION);
try { try {
ssData >> a_sk; ssData >> k;
ssData >> sk_enc;
} catch(const std::exception &) { } catch(const std::exception &) {
throw runtime_error( throw runtime_error(
"zcsecretkey could not be decoded" "zcsecretkey could not be decoded"
@@ -2469,12 +2469,10 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
} }
} }
libzerocash::PrivateAddress zcsecretkey(a_sk, sk_enc);
libzerocash::Address zcaddress(zcsecretkey);
uint256 epk; uint256 epk;
unsigned char nonce; unsigned char nonce;
ZCNoteEncryption::Ciphertext ct; ZCNoteEncryption::Ciphertext ct;
uint256 h_sig;
{ {
CDataStream ssData(ParseHexV(params[1], "encrypted_bucket"), SER_NETWORK, PROTOCOL_VERSION); CDataStream ssData(ParseHexV(params[1], "encrypted_bucket"), SER_NETWORK, PROTOCOL_VERSION);
@@ -2482,6 +2480,7 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
ssData >> nonce; ssData >> nonce;
ssData >> epk; ssData >> epk;
ssData >> ct; ssData >> ct;
ssData >> h_sig;
} catch(const std::exception &) { } catch(const std::exception &) {
throw runtime_error( throw runtime_error(
"encrypted_bucket could not be decoded" "encrypted_bucket could not be decoded"
@@ -2489,32 +2488,40 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
} }
} }
libzerocash::Coin decrypted_bucket(ct, zcaddress, epk, nonce); ZCNoteDecryption decryptor(k.viewing_key());
std::vector<unsigned char> commitment_v = decrypted_bucket.getCoinCommitment().getCommitmentValue(); NotePlaintext npt = NotePlaintext::decrypt(
uint256 commitment = uint256(commitment_v); decryptor,
ct,
epk,
h_sig,
nonce
);
PaymentAddress payment_addr = k.address();
Note decrypted_note = npt.note(payment_addr);
assert(pwalletMain != NULL); assert(pwalletMain != NULL);
libzcash::MerklePath path; std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
uint256 anchor; uint256 anchor;
auto found_in_chain = pwalletMain->WitnessBucketCommitment(commitment, path, anchor); uint256 commitment = decrypted_note.cm();
pwalletMain->WitnessBucketCommitment(
CAmount value_of_bucket = decrypted_bucket.getValue(); {commitment},
witnesses,
anchor
);
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
{ ss << npt;
ss << decrypted_bucket.getValue();
ss << decrypted_bucket.getRho();
ss << decrypted_bucket.getR();
}
Object result; Object result;
result.push_back(Pair("amount", ValueFromAmount(value_of_bucket))); result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value)));
result.push_back(Pair("bucket", HexStr(ss.begin(), ss.end()))); result.push_back(Pair("bucket", HexStr(ss.begin(), ss.end())));
result.push_back(Pair("exists", found_in_chain)); result.push_back(Pair("exists", (bool) witnesses[0]));
return result; return result;
} }
Value zc_raw_pour(const json_spirit::Array& params, bool fHelp) Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
{ {
if (!EnsureWalletIsAvailable(fHelp)) { if (!EnsureWalletIsAvailable(fHelp)) {
@@ -2563,30 +2570,20 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
if (params[4].get_real() != 0.0) if (params[4].get_real() != 0.0)
vpub_new = AmountFromValue(params[4]); vpub_new = AmountFromValue(params[4]);
std::vector<PourInput> vpourin; std::vector<JSInput> vpourin;
std::vector<PourOutput> vpourout; std::vector<JSOutput> vpourout;
std::vector<Note> notes;
uint256 anchor; std::vector<SpendingKey> keys;
std::vector<uint256> commitments;
BOOST_FOREACH(const Pair& s, inputs) BOOST_FOREACH(const Pair& s, inputs)
{ {
CDataStream ssData(ParseHexV(s.name_, "bucket"), SER_NETWORK, PROTOCOL_VERSION); SpendingKey k;
uint64_t value;
std::vector<unsigned char> rho;
std::vector<unsigned char> r;
ssData >> value;
ssData >> rho;
ssData >> r;
uint256 a_sk;
uint256 sk_enc;
{ {
CDataStream ssData2(ParseHexV(s.value_, "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION); CDataStream ssData(ParseHexV(s.value_, "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION);
try { try {
ssData2 >> a_sk; ssData >> k;
ssData2 >> sk_enc;
} catch(const std::exception &) { } catch(const std::exception &) {
throw runtime_error( throw runtime_error(
"zcsecretkey could not be decoded" "zcsecretkey could not be decoded"
@@ -2594,51 +2591,58 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
} }
} }
libzerocash::PrivateAddress zcsecretkey(a_sk, sk_enc); keys.push_back(k);
libzerocash::Address zcaddress(zcsecretkey);
libzerocash::Coin input_coin(zcaddress.getPublicAddress(), value, rho, r);
std::vector<unsigned char> commitment_v = input_coin.getCoinCommitment().getCommitmentValue(); NotePlaintext npt;
uint256 commitment = uint256(commitment_v);
libzcash::MerklePath path; {
assert(pwalletMain != NULL); CDataStream ssData(ParseHexV(s.name_, "bucket"), SER_NETWORK, PROTOCOL_VERSION);
if (!pwalletMain->WitnessBucketCommitment(commitment, path, anchor)) { ssData >> npt;
throw std::runtime_error("Couldn't find bucket in the blockchain");
} }
vpourin.push_back(PourInput(input_coin, zcaddress, path)); PaymentAddress addr = k.address();
Note note = npt.note(addr);
notes.push_back(note);
commitments.push_back(note.cm());
}
uint256 anchor;
std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
pwalletMain->WitnessBucketCommitment(commitments, witnesses, anchor);
assert(witnesses.size() == notes.size());
assert(notes.size() == keys.size());
{
for (size_t i = 0; i < witnesses.size(); i++) {
if (!witnesses[i]) {
throw runtime_error(
"pour input could not be found in tree"
);
}
vpourin.push_back(JSInput(*witnesses[i], notes[i], keys[i]));
}
} }
while (vpourin.size() < ZC_NUM_JS_INPUTS) { while (vpourin.size() < ZC_NUM_JS_INPUTS) {
vpourin.push_back(PourInput(INCREMENTAL_MERKLE_TREE_DEPTH)); vpourin.push_back(JSInput());
} }
BOOST_FOREACH(const Pair& s, outputs) BOOST_FOREACH(const Pair& s, outputs)
{ {
libzerocash::PublicAddress addrTo; PaymentAddress addrTo;
{ {
CDataStream ssData(ParseHexV(s.name_, "to_address"), SER_NETWORK, PROTOCOL_VERSION); CDataStream ssData(ParseHexV(s.name_, "to_address"), SER_NETWORK, PROTOCOL_VERSION);
ssData >> addrTo;
uint256 pubAddressSecret;
uint256 encryptionPublicKey;
ssData >> pubAddressSecret;
ssData >> encryptionPublicKey;
addrTo = libzerocash::PublicAddress(pubAddressSecret, encryptionPublicKey);
} }
CAmount nAmount = AmountFromValue(s.value_); CAmount nAmount = AmountFromValue(s.value_);
libzerocash::Coin coin(addrTo, nAmount); vpourout.push_back(JSOutput(addrTo, nAmount));
libzerocash::PourOutput output(coin, addrTo);
vpourout.push_back(output);
} }
while (vpourout.size() < ZC_NUM_JS_OUTPUTS) { while (vpourout.size() < ZC_NUM_JS_OUTPUTS) {
vpourout.push_back(PourOutput(0)); vpourout.push_back(JSOutput());
} }
// TODO // TODO
@@ -2648,7 +2652,7 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
// TODO: #808 // TODO: #808
uint256 pubKeyHash; uint256 pubKeyHash;
CPourTx pourtx(*pzerocashParams, CPourTx pourtx(*pzcashParams,
pubKeyHash, pubKeyHash,
anchor, anchor,
{vpourin[0], vpourin[1]}, {vpourin[0], vpourin[1]},
@@ -2656,7 +2660,7 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
vpub_old, vpub_old,
vpub_new); vpub_new);
assert(pourtx.Verify(*pzerocashParams, pubKeyHash)); assert(pourtx.Verify(*pzcashParams, pubKeyHash));
CMutableTransaction mtx(tx); CMutableTransaction mtx(tx);
mtx.nVersion = 2; mtx.nVersion = 2;
@@ -2674,6 +2678,7 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
ss2 << ((unsigned char) 0x00); ss2 << ((unsigned char) 0x00);
ss2 << pourtx.ephemeralKey; ss2 << pourtx.ephemeralKey;
ss2 << pourtx.ciphertexts[0]; ss2 << pourtx.ciphertexts[0];
ss2 << pourtx.h_sig(*pzcashParams, pubKeyHash);
encryptedBucket1 = HexStr(ss2.begin(), ss2.end()); encryptedBucket1 = HexStr(ss2.begin(), ss2.end());
} }
@@ -2682,6 +2687,7 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
ss2 << ((unsigned char) 0x01); ss2 << ((unsigned char) 0x01);
ss2 << pourtx.ephemeralKey; ss2 << pourtx.ephemeralKey;
ss2 << pourtx.ciphertexts[1]; ss2 << pourtx.ciphertexts[1];
ss2 << pourtx.h_sig(*pzcashParams, pubKeyHash);
encryptedBucket2 = HexStr(ss2.begin(), ss2.end()); encryptedBucket2 = HexStr(ss2.begin(), ss2.end());
} }
@@ -2712,22 +2718,25 @@ Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp)
); );
} }
auto zckeypair = libzerocash::Address::CreateNewRandomAddress(); auto k = SpendingKey::random();
auto addr = k.address();
auto viewing_key = k.viewing_key();
CDataStream pub(SER_NETWORK, PROTOCOL_VERSION); CDataStream pub(SER_NETWORK, PROTOCOL_VERSION);
CDataStream priv(SER_NETWORK, PROTOCOL_VERSION); CDataStream priv(SER_NETWORK, PROTOCOL_VERSION);
CDataStream viewing(SER_NETWORK, PROTOCOL_VERSION);
pub << zckeypair.getPublicAddress().getPublicAddressSecret(); // a_pk pub << addr;
pub << zckeypair.getPublicAddress().getEncryptionPublicKey(); // pk_enc priv << k;
viewing << viewing_key;
priv << zckeypair.getPrivateAddress().getAddressSecret(); // a_sk
priv << zckeypair.getPrivateAddress().getEncryptionSecretKey(); // sk_enc
std::string pub_hex = HexStr(pub.begin(), pub.end()); std::string pub_hex = HexStr(pub.begin(), pub.end());
std::string priv_hex = HexStr(priv.begin(), priv.end()); std::string priv_hex = HexStr(priv.begin(), priv.end());
std::string viewing_hex = HexStr(viewing.begin(), viewing.end());
Object result; Object result;
result.push_back(Pair("zcaddress", pub_hex)); result.push_back(Pair("zcaddress", pub_hex));
result.push_back(Pair("zcsecretkey", priv_hex)); result.push_back(Pair("zcsecretkey", priv_hex));
result.push_back(Pair("zcviewingkey", viewing_hex));
return result; return result;
} }

View File

@@ -1051,13 +1051,13 @@ bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
return pwalletdb->WriteTx(GetHash(), *this); return pwalletdb->WriteTx(GetHash(), *this);
} }
bool CWallet::WitnessBucketCommitment(uint256 &commitment, void CWallet::WitnessBucketCommitment(std::vector<uint256> commitments,
libzcash::MerklePath &path, std::vector<boost::optional<ZCIncrementalWitness>>& witnesses,
uint256 &final_anchor) uint256 &final_anchor)
{ {
witnesses.resize(commitments.size());
CBlockIndex* pindex = chainActive.Genesis(); CBlockIndex* pindex = chainActive.Genesis();
ZCIncrementalMerkleTree tree; ZCIncrementalMerkleTree tree;
boost::optional<ZCIncrementalWitness> witness = boost::none;
uint256 current_anchor; uint256 current_anchor;
while (pindex) { while (pindex) {
@@ -1070,24 +1070,26 @@ bool CWallet::WitnessBucketCommitment(uint256 &commitment,
{ {
BOOST_FOREACH(const uint256 &bucket_commitment, pour.commitments) BOOST_FOREACH(const uint256 &bucket_commitment, pour.commitments)
{ {
if (witness) { tree.append(bucket_commitment);
witness->append(bucket_commitment);
} else {
tree.append(bucket_commitment);
if (bucket_commitment == commitment) { BOOST_FOREACH(boost::optional<ZCIncrementalWitness>& wit, witnesses) {
witness = tree.witness(); if (wit) {
wit->append(bucket_commitment);
} }
} }
size_t i = 0;
BOOST_FOREACH(uint256& commitment, commitments) {
if (bucket_commitment == commitment) {
witnesses.at(i) = tree.witness();
}
i++;
}
} }
} }
} }
if (witness) { current_anchor = tree.root();
current_anchor = witness->root();
} else {
current_anchor = tree.root();
}
// Consistency check: we should be able to find the current tree // Consistency check: we should be able to find the current tree
// in our CCoins view. // in our CCoins view.
@@ -1097,14 +1099,13 @@ bool CWallet::WitnessBucketCommitment(uint256 &commitment,
pindex = chainActive.Next(pindex); pindex = chainActive.Next(pindex);
} }
if (witness) { final_anchor = current_anchor;
path = witness->path();
final_anchor = current_anchor;
return true; BOOST_FOREACH(boost::optional<ZCIncrementalWitness>& wit, witnesses) {
if (wit) {
assert(final_anchor == wit->root());
}
} }
return false;
} }
/** /**

View File

@@ -616,7 +616,10 @@ public:
void SyncTransaction(const CTransaction& tx, const CBlock* pblock); void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
void EraseFromWallet(const uint256 &hash); void EraseFromWallet(const uint256 &hash);
bool WitnessBucketCommitment(uint256 &commitment, libzcash::MerklePath& path, uint256 &final_anchor); void WitnessBucketCommitment(
std::vector<uint256> commitments,
std::vector<boost::optional<ZCIncrementalWitness>>& witnesses,
uint256 &final_anchor);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions(); void ReacceptWalletTransactions();
void ResendWalletTransactions(int64_t nBestBlockTime); void ResendWalletTransactions(int64_t nBestBlockTime);

View File

@@ -1,9 +1,5 @@
#include "zerocash/IncrementalMerkleTree.h"
#include <unistd.h> #include <unistd.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include "zcash/Zcash.h"
#include "zerocash/ZerocashParams.h"
#include "coins.h" #include "coins.h"
#include "util.h" #include "util.h"
#include "init.h" #include "init.h"
@@ -16,6 +12,11 @@
#include "zcbenchmarks.h" #include "zcbenchmarks.h"
#include "zcash/Zcash.h"
#include "zcash/IncrementalMerkleTree.hpp"
using namespace libzcash;
struct timeval tv_start; struct timeval tv_start;
void timer_start() void timer_start()
@@ -47,20 +48,18 @@ double benchmark_parameter_loading()
boost::filesystem::path vk_path = ZC_GetParamsDir() / "zc-testnet-public-alpha-verification.key"; boost::filesystem::path vk_path = ZC_GetParamsDir() / "zc-testnet-public-alpha-verification.key";
timer_start(); timer_start();
auto vk_loaded = libzerocash::ZerocashParams::LoadVerificationKeyFromFile(
vk_path.string(), auto newParams = ZCJoinSplit::Unopened();
INCREMENTAL_MERKLE_TREE_DEPTH
); newParams->loadVerifyingKey(vk_path.string());
auto pk_loaded = libzerocash::ZerocashParams::LoadProvingKeyFromFile( newParams->setProvingKeyPath(pk_path.string());
pk_path.string(), newParams->loadProvingKey();
INCREMENTAL_MERKLE_TREE_DEPTH
); double ret = timer_stop();
libzerocash::ZerocashParams zerocashParams = libzerocash::ZerocashParams(
INCREMENTAL_MERKLE_TREE_DEPTH, delete newParams;
&pk_loaded,
&vk_loaded return ret;
);
return timer_stop();
} }
double benchmark_create_joinsplit() double benchmark_create_joinsplit()
@@ -68,31 +67,20 @@ double benchmark_create_joinsplit()
// TODO: #808 // TODO: #808
uint256 pubKeyHash; uint256 pubKeyHash;
std::vector<PourInput> vpourin;
std::vector<PourOutput> vpourout;
while (vpourin.size() < ZC_NUM_JS_INPUTS) {
vpourin.push_back(PourInput(INCREMENTAL_MERKLE_TREE_DEPTH));
}
while (vpourout.size() < ZC_NUM_JS_OUTPUTS) {
vpourout.push_back(PourOutput(0));
}
/* Get the anchor of an empty commitment tree. */ /* Get the anchor of an empty commitment tree. */
uint256 anchor = ZCIncrementalMerkleTree().root(); uint256 anchor = ZCIncrementalMerkleTree().root();
timer_start(); timer_start();
CPourTx pourtx(*pzerocashParams, CPourTx pourtx(*pzcashParams,
pubKeyHash, pubKeyHash,
anchor, anchor,
{vpourin[0], vpourin[1]}, {JSInput(), JSInput()},
{vpourout[0], vpourout[1]}, {JSOutput(), JSOutput()},
0, 0,
0); 0);
double ret = timer_stop(); double ret = timer_stop();
assert(pourtx.Verify(*pzerocashParams, pubKeyHash)); assert(pourtx.Verify(*pzcashParams, pubKeyHash));
return ret; return ret;
} }
@@ -101,7 +89,7 @@ double benchmark_verify_joinsplit(const CPourTx &joinsplit)
timer_start(); timer_start();
// TODO: #808 // TODO: #808
uint256 pubKeyHash; uint256 pubKeyHash;
joinsplit.Verify(*pzerocashParams, pubKeyHash); joinsplit.Verify(*pzcashParams, pubKeyHash);
return timer_stop(); return timer_stop();
} }