Merge remote-tracking branch 'zcash/master' into rebase2

# Conflicts:
#	.travis.yml
#	Makefile.am
#	README.md
#	configure.ac
#	depends/Makefile
#	depends/builders/darwin.mk
#	depends/funcs.mk
#	depends/hosts/darwin.mk
#	depends/packages/googlemock.mk
#	depends/packages/googletest.mk
#	depends/packages/libsnark.mk
#	depends/packages/libsodium.mk
#	depends/packages/packages.mk
#	depends/packages/rust.mk
#	src/Makefile.am
#	src/Makefile.gtest.include
#	src/chainparams.cpp
#	src/chainparams.h
#	src/checkpoints.h
#	src/clientversion.h
#	src/coins.cpp
#	src/consensus/consensus.h
#	src/gtest/test_mempool.cpp
#	src/httprpc.cpp
#	src/init.cpp
#	src/komodo-tx.cpp
#	src/main.cpp
#	src/miner.cpp
#	src/policy/fees.cpp
#	src/policy/fees.h
#	src/rpcmining.cpp
#	src/rpcrawtransaction.cpp
#	src/rpcserver.cpp
#	src/test/policyestimator_tests.cpp
#	src/test/rpc_wallet_tests.cpp
#	src/test/transaction_tests.cpp
#	src/txdb.cpp
#	src/txmempool.cpp
#	src/wallet/asyncrpcoperation_sendmany.cpp
#	src/wallet/rpcwallet.cpp
#	src/wallet/wallet.cpp
#	src/wallet/wallet.h
#	src/zcash/CreateJoinSplit.cpp
#	zcutil/build.sh
This commit is contained in:
jl777
2018-03-25 18:44:38 +03:00
603 changed files with 55577 additions and 9837 deletions

View File

@@ -12,12 +12,20 @@ uint256 PaymentAddress::GetHash() const {
return Hash(ss.begin(), ss.end());
}
uint256 ViewingKey::pk_enc() {
uint256 ReceivingKey::pk_enc() const {
return ZCNoteEncryption::generate_pubkey(*this);
}
PaymentAddress ViewingKey::address() const {
return PaymentAddress(a_pk, sk_enc.pk_enc());
}
ReceivingKey SpendingKey::receiving_key() const {
return ReceivingKey(ZCNoteEncryption::generate_privkey(*this));
}
ViewingKey SpendingKey::viewing_key() const {
return ViewingKey(ZCNoteEncryption::generate_privkey(*this));
return ViewingKey(PRF_addr_a_pk(*this), receiving_key());
}
SpendingKey SpendingKey::random() {
@@ -25,7 +33,7 @@ SpendingKey SpendingKey::random() {
}
PaymentAddress SpendingKey::address() const {
return PaymentAddress(PRF_addr_a_pk(*this), viewing_key().pk_enc());
return viewing_key().address();
}
}

View File

@@ -1,5 +1,5 @@
#ifndef _ZCADDRESS_H_
#define _ZCADDRESS_H_
#ifndef ZC_ADDRESS_H_
#define ZC_ADDRESS_H_
#include "uint256.h"
#include "uint252.h"
@@ -8,6 +8,7 @@
namespace libzcash {
const size_t SerializedPaymentAddressSize = 64;
const size_t SerializedViewingKeySize = 64;
const size_t SerializedSpendingKeySize = 32;
class PaymentAddress {
@@ -38,11 +39,39 @@ public:
}
};
class ViewingKey : public uint256 {
class ReceivingKey : public uint256 {
public:
ViewingKey(uint256 sk_enc) : uint256(sk_enc) { }
ReceivingKey() { }
ReceivingKey(uint256 sk_enc) : uint256(sk_enc) { }
uint256 pk_enc();
uint256 pk_enc() const;
};
class ViewingKey {
public:
uint256 a_pk;
ReceivingKey sk_enc;
ViewingKey() : a_pk(), sk_enc() { }
ViewingKey(uint256 a_pk, ReceivingKey sk_enc) : a_pk(a_pk), sk_enc(sk_enc) { }
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(a_pk);
READWRITE(sk_enc);
}
PaymentAddress address() const;
friend inline bool operator==(const ViewingKey& a, const ViewingKey& b) {
return a.a_pk == b.a_pk && a.sk_enc == b.sk_enc;
}
friend inline bool operator<(const ViewingKey& a, const ViewingKey& b) {
return (a.a_pk < b.a_pk ||
(a.a_pk == b.a_pk && a.sk_enc < b.sk_enc));
}
};
class SpendingKey : public uint252 {
@@ -52,10 +81,11 @@ public:
static SpendingKey random();
ReceivingKey receiving_key() const;
ViewingKey viewing_key() const;
PaymentAddress address() const;
};
}
#endif // _ZCADDRESS_H_
#endif // ZC_ADDRESS_H_

View File

@@ -5,6 +5,7 @@
#include "../util.h"
#include "primitives/transaction.h"
#include "zcash/JoinSplit.hpp"
#include "libsnark/common/profiling.hpp"
#include "komodo_defs.h"
char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
@@ -17,10 +18,8 @@ int main(int argc, char **argv)
{
libsnark::start_profiling();
auto p = ZCJoinSplit::Unopened();
p->loadVerifyingKey((ZC_GetParamsDir() / "sprout-verifying.key").string());
p->setProvingKeyPath((ZC_GetParamsDir() / "sprout-proving.key").string());
p->loadProvingKey();
auto p = ZCJoinSplit::Prepared((ZC_GetParamsDir() / "sprout-verifying.key").string(),
(ZC_GetParamsDir() / "sprout-proving.key").string());
// construct a proof.
@@ -36,4 +35,6 @@ int main(int argc, char **argv)
0,
0);
}
delete p; // not that it matters
}

View File

@@ -20,13 +20,7 @@ int main(int argc, char **argv)
std::string vkFile = argv[2];
std::string r1csFile = argv[3];
auto p = ZCJoinSplit::Generate();
p->saveProvingKey(pkFile);
p->saveVerifyingKey(vkFile);
p->saveR1CS(r1csFile);
delete p;
ZCJoinSplit::Generate(r1csFile, vkFile, pkFile);
return 0;
}

View File

@@ -1,5 +1,5 @@
#ifndef ZCINCREMENTALMERKLETREE_H_
#define ZCINCREMENTALMERKLETREE_H_
#ifndef ZC_INCREMENTALMERKLETREE_H_
#define ZC_INCREMENTALMERKLETREE_H_
#include <deque>
#include <boost/optional.hpp>
@@ -202,5 +202,4 @@ typedef libzcash::IncrementalMerkleTree<INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, l
typedef libzcash::IncrementalWitness<INCREMENTAL_MERKLE_TREE_DEPTH, libzcash::SHA256Compress> ZCIncrementalWitness;
typedef libzcash::IncrementalWitness<INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, libzcash::SHA256Compress> ZCTestingIncrementalWitness;
#endif /* ZCINCREMENTALMERKLETREE_H_ */
#endif /* ZC_INCREMENTALMERKLETREE_H_ */

View File

@@ -10,11 +10,11 @@
#include <boost/format.hpp>
#include <boost/optional.hpp>
#include <fstream>
#include "libsnark/common/default_types/r1cs_ppzksnark_pp.hpp"
#include "libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp"
#include "libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp"
#include "libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp"
#include <libsnark/common/default_types/r1cs_ppzksnark_pp.hpp>
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
#include <libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp>
#include <libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp>
#include "tinyformat.h"
#include "sync.h"
#include "amount.h"
@@ -28,7 +28,7 @@ CCriticalSection cs_ParamsIO;
CCriticalSection cs_LoadKeys;
template<typename T>
void saveToFile(std::string path, T& obj) {
void saveToFile(const std::string path, T& obj) {
LOCK(cs_ParamsIO);
std::stringstream ss;
@@ -42,14 +42,14 @@ void saveToFile(std::string path, T& obj) {
}
template<typename T>
void loadFromFile(std::string path, boost::optional<T>& objIn) {
void loadFromFile(const std::string path, T& objIn) {
LOCK(cs_ParamsIO);
std::stringstream ss;
std::ifstream fh(path, std::ios::binary);
if(!fh.is_open()) {
throw std::runtime_error((boost::format("could not load param file at %s") % path).str());
throw std::runtime_error(strprintf("could not load param file at %s", path));
}
ss << fh.rdbuf();
@@ -69,77 +69,33 @@ public:
typedef default_r1cs_ppzksnark_pp ppzksnark_ppT;
typedef Fr<ppzksnark_ppT> FieldT;
boost::optional<r1cs_ppzksnark_proving_key<ppzksnark_ppT>> pk;
boost::optional<r1cs_ppzksnark_verification_key<ppzksnark_ppT>> vk;
boost::optional<r1cs_ppzksnark_processed_verification_key<ppzksnark_ppT>> vk_precomp;
boost::optional<std::string> pkPath;
r1cs_ppzksnark_verification_key<ppzksnark_ppT> vk;
r1cs_ppzksnark_processed_verification_key<ppzksnark_ppT> vk_precomp;
std::string pkPath;
JoinSplitCircuit() {}
JoinSplitCircuit(const std::string vkPath, const std::string pkPath) : pkPath(pkPath) {
loadFromFile(vkPath, vk);
vk_precomp = r1cs_ppzksnark_verifier_process_vk(vk);
}
~JoinSplitCircuit() {}
void setProvingKeyPath(std::string path) {
pkPath = path;
}
void loadProvingKey() {
LOCK(cs_LoadKeys);
if (!pk) {
if (!pkPath) {
throw std::runtime_error("proving key path unknown");
}
loadFromFile(*pkPath, pk);
}
}
void saveProvingKey(std::string path) {
if (pk) {
saveToFile(path, *pk);
} else {
throw std::runtime_error("cannot save proving key; key doesn't exist");
}
}
void loadVerifyingKey(std::string path) {
LOCK(cs_LoadKeys);
loadFromFile(path, vk);
processVerifyingKey();
}
void processVerifyingKey() {
vk_precomp = r1cs_ppzksnark_verifier_process_vk(*vk);
}
void saveVerifyingKey(std::string path) {
if (vk) {
saveToFile(path, *vk);
} else {
throw std::runtime_error("cannot save verifying key; key doesn't exist");
}
}
void saveR1CS(std::string path) {
auto r1cs = generate_r1cs();
saveToFile(path, r1cs);
}
r1cs_constraint_system<FieldT> generate_r1cs() {
static void generate(const std::string r1csPath,
const std::string vkPath,
const std::string pkPath)
{
protoboard<FieldT> pb;
joinsplit_gadget<FieldT, NumInputs, NumOutputs> g(pb);
g.generate_r1cs_constraints();
return pb.get_constraint_system();
}
auto r1cs = pb.get_constraint_system();
void generate() {
LOCK(cs_LoadKeys);
saveToFile(r1csPath, r1cs);
const r1cs_constraint_system<FieldT> constraint_system = generate_r1cs();
r1cs_ppzksnark_keypair<ppzksnark_ppT> keypair = r1cs_ppzksnark_generator<ppzksnark_ppT>(constraint_system);
r1cs_ppzksnark_keypair<ppzksnark_ppT> keypair = r1cs_ppzksnark_generator<ppzksnark_ppT>(r1cs);
pk = keypair.pk;
vk = keypair.vk;
processVerifyingKey();
saveToFile(vkPath, keypair.vk);
saveToFile(pkPath, keypair.pk);
}
bool verify(
@@ -154,10 +110,6 @@ public:
uint64_t vpub_new,
const uint256& rt
) {
if (!vk || !vk_precomp) {
throw std::runtime_error("JoinSplit verifying key not loaded");
}
try {
auto r1cs_proof = proof.to_libsnark_proof<r1cs_ppzksnark_proof<ppzksnark_ppT>>();
@@ -174,8 +126,8 @@ public:
);
return verifier.check(
*vk,
*vk_precomp,
vk,
vk_precomp,
witness,
r1cs_proof
);
@@ -198,12 +150,9 @@ public:
uint64_t vpub_old,
uint64_t vpub_new,
const uint256& rt,
bool computeProof
bool computeProof,
uint256 *out_esk // Payment disclosure
) {
if (computeProof && !pk) {
throw std::runtime_error("JoinSplit proving key not loaded");
}
if (vpub_old > MAX_MONEY) {
throw std::invalid_argument("nonsensical vpub_old value");
}
@@ -303,6 +252,12 @@ public:
}
out_ephemeralKey = encryptor.get_epk();
// !!! Payment disclosure START
if (out_esk != nullptr) {
*out_esk = encryptor.get_esk();
}
// !!! Payment disclosure END
}
// Authenticate h_sig with each of the input
@@ -345,8 +300,14 @@ public:
// estimate that it doesn't matter if we check every time.
pb.constraint_system.swap_AB_if_beneficial();
return ZCProof(r1cs_ppzksnark_prover<ppzksnark_ppT>(
*pk,
std::ifstream fh(pkPath, std::ios::binary);
if(!fh.is_open()) {
throw std::runtime_error(strprintf("could not load param file at %s", pkPath));
}
return ZCProof(r1cs_ppzksnark_prover_streaming<ppzksnark_ppT>(
fh,
primary_input,
aux_input,
pb.constraint_system
@@ -355,20 +316,20 @@ public:
};
template<size_t NumInputs, size_t NumOutputs>
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Generate()
void JoinSplit<NumInputs, NumOutputs>::Generate(const std::string r1csPath,
const std::string vkPath,
const std::string pkPath)
{
initialize_curve_params();
auto js = new JoinSplitCircuit<NumInputs, NumOutputs>();
js->generate();
return js;
JoinSplitCircuit<NumInputs, NumOutputs>::generate(r1csPath, vkPath, pkPath);
}
template<size_t NumInputs, size_t NumOutputs>
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Unopened()
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Prepared(const std::string vkPath,
const std::string pkPath)
{
initialize_curve_params();
return new JoinSplitCircuit<NumInputs, NumOutputs>();
return new JoinSplitCircuit<NumInputs, NumOutputs>(vkPath, pkPath);
}
template<size_t NumInputs, size_t NumOutputs>

View File

@@ -1,5 +1,5 @@
#ifndef _ZCJOINSPLIT_H_
#define _ZCJOINSPLIT_H_
#ifndef ZC_JOINSPLIT_H_
#define ZC_JOINSPLIT_H_
#include "Zcash.h"
#include "Proof.hpp"
@@ -48,22 +48,17 @@ class JoinSplit {
public:
virtual ~JoinSplit() {}
static JoinSplit<NumInputs, NumOutputs>* Generate();
static JoinSplit<NumInputs, NumOutputs>* Unopened();
static void Generate(const std::string r1csPath,
const std::string vkPath,
const std::string pkPath);
static JoinSplit<NumInputs, NumOutputs>* Prepared(const std::string vkPath,
const std::string pkPath);
static uint256 h_sig(const uint256& randomSeed,
const boost::array<uint256, NumInputs>& nullifiers,
const uint256& pubKeyHash
);
// TODO: #789
virtual void setProvingKeyPath(std::string) = 0;
virtual void loadProvingKey() = 0;
virtual void saveProvingKey(std::string path) = 0;
virtual void loadVerifyingKey(std::string path) = 0;
virtual void saveVerifyingKey(std::string path) = 0;
virtual void saveR1CS(std::string path) = 0;
virtual ZCProof prove(
const boost::array<JSInput, NumInputs>& inputs,
const boost::array<JSOutput, NumOutputs>& outputs,
@@ -78,7 +73,11 @@ public:
uint64_t vpub_old,
uint64_t vpub_new,
const uint256& rt,
bool computeProof = true
bool computeProof = true,
// For paymentdisclosure, we need to retrieve the esk.
// Reference as non-const parameter with default value leads to compile error.
// So use pointer for simplicity.
uint256 *out_esk = nullptr
) = 0;
virtual bool verify(
@@ -103,4 +102,4 @@ protected:
typedef libzcash::JoinSplit<ZC_NUM_JS_INPUTS,
ZC_NUM_JS_OUTPUTS> ZCJoinSplit;
#endif // _ZCJOINSPLIT_H_
#endif // ZC_JOINSPLIT_H_

View File

@@ -1,5 +1,5 @@
#ifndef _ZCNOTE_H_
#define _ZCNOTE_H_
#ifndef ZC_NOTE_H_
#define ZC_NOTE_H_
#include "uint256.h"
#include "Zcash.h"
@@ -68,4 +68,4 @@ public:
}
#endif // _ZCNOTE_H_
#endif // ZC_NOTE_H_

View File

@@ -135,6 +135,52 @@ typename NoteDecryption<MLEN>::Plaintext NoteDecryption<MLEN>::decrypt
return plaintext;
}
//
// Payment disclosure - decrypt with esk
//
template<size_t MLEN>
typename PaymentDisclosureNoteDecryption<MLEN>::Plaintext PaymentDisclosureNoteDecryption<MLEN>::decryptWithEsk
(const PaymentDisclosureNoteDecryption<MLEN>::Ciphertext &ciphertext,
const uint256 &pk_enc,
const uint256 &esk,
const uint256 &hSig,
unsigned char nonce
) const
{
uint256 dhsecret;
if (crypto_scalarmult(dhsecret.begin(), esk.begin(), pk_enc.begin()) != 0) {
throw std::logic_error("Could not create DH secret");
}
// Regenerate keypair
uint256 epk = NoteEncryption<MLEN>::generate_pubkey(esk);
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE];
KDF(K, dhsecret, epk, pk_enc, hSig, nonce);
// The nonce is zero because we never reuse keys
unsigned char cipher_nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] = {};
PaymentDisclosureNoteDecryption<MLEN>::Plaintext plaintext;
// Message length is always NOTEENCRYPTION_AUTH_BYTES less than
// the ciphertext length.
if (crypto_aead_chacha20poly1305_ietf_decrypt(plaintext.begin(), NULL,
NULL,
ciphertext.begin(), PaymentDisclosureNoteDecryption<MLEN>::CLEN,
NULL,
0,
cipher_nonce, K) != 0) {
throw note_decryption_failed();
}
return plaintext;
}
template<size_t MLEN>
uint256 NoteEncryption<MLEN>::generate_privkey(const uint252 &a_sk)
{
@@ -176,4 +222,6 @@ uint252 random_uint252()
template class NoteEncryption<ZC_NOTEPLAINTEXT_SIZE>;
template class NoteDecryption<ZC_NOTEPLAINTEXT_SIZE>;
template class PaymentDisclosureNoteDecryption<ZC_NOTEPLAINTEXT_SIZE>;
}

View File

@@ -31,6 +31,11 @@ public:
NoteEncryption(uint256 hSig);
// Gets the ephemeral secret key
uint256 get_esk() {
return esk;
}
// Gets the ephemeral public key
uint256 get_epk() {
return epk;
@@ -87,9 +92,34 @@ public:
note_decryption_failed() : std::runtime_error("Could not decrypt message") { }
};
// Subclass PaymentDisclosureNoteDecryption provides a method to decrypt a note with esk.
template<size_t MLEN>
class PaymentDisclosureNoteDecryption : public NoteDecryption<MLEN> {
protected:
public:
enum { CLEN=MLEN+NOTEENCRYPTION_AUTH_BYTES };
typedef boost::array<unsigned char, CLEN> Ciphertext;
typedef boost::array<unsigned char, MLEN> Plaintext;
PaymentDisclosureNoteDecryption() : NoteDecryption<MLEN>() {}
PaymentDisclosureNoteDecryption(uint256 sk_enc) : NoteDecryption<MLEN>(sk_enc) {}
Plaintext decryptWithEsk(
const Ciphertext &ciphertext,
const uint256 &pk_enc,
const uint256 &esk,
const uint256 &hSig,
unsigned char nonce
) const;
};
}
typedef libzcash::NoteEncryption<ZC_NOTEPLAINTEXT_SIZE> ZCNoteEncryption;
typedef libzcash::NoteDecryption<ZC_NOTEPLAINTEXT_SIZE> ZCNoteDecryption;
typedef libzcash::PaymentDisclosureNoteDecryption<ZC_NOTEPLAINTEXT_SIZE> ZCPaymentDisclosureNoteDecryption;
#endif /* ZC_NOTE_ENCRYPTION_H_ */

View File

@@ -1,11 +1,11 @@
#include "Proof.hpp"
#include <boost/static_assert.hpp>
#include <mutex>
#include "crypto/common.h"
#include "libsnark/common/default_types/r1cs_ppzksnark_pp.hpp"
#include "libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp"
#include <boost/static_assert.hpp>
#include <libsnark/common/default_types/r1cs_ppzksnark_pp.hpp>
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
#include <mutex>
using namespace libsnark;

View File

@@ -1,5 +1,5 @@
#ifndef _ZCPROOF_H_
#define _ZCPROOF_H_
#ifndef ZC_PROOF_H_
#define ZC_PROOF_H_
#include "serialize.h"
#include "uint256.h"
@@ -274,4 +274,4 @@ public:
}
#endif // _ZCPROOF_H_
#endif // ZC_PROOF_H_

View File

@@ -1,5 +1,5 @@
#ifndef _ZCCONSTANTS_H_
#define _ZCCONSTANTS_H_
#ifndef ZC_ZCASH_H_
#define ZC_ZCASH_H_
#define ZC_NUM_JS_INPUTS 2
#define ZC_NUM_JS_OUTPUTS 2
@@ -14,4 +14,4 @@
#define ZC_NOTEPLAINTEXT_SIZE (ZC_NOTEPLAINTEXT_LEADING + ZC_V_SIZE + ZC_RHO_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE)
#endif // _ZCCONSTANTS_H_
#endif // ZC_ZCASH_H_

View File

@@ -3,8 +3,8 @@ Zcash uses SHA256Compress as a PRF for various components
within the zkSNARK circuit.
*/
#ifndef _PRF_H_
#define _PRF_H_
#ifndef ZC_PRF_H_
#define ZC_PRF_H_
#include "uint256.h"
#include "uint252.h"
@@ -15,4 +15,4 @@ uint256 PRF_nf(const uint252& a_sk, const uint256& rho);
uint256 PRF_pk(const uint252& a_sk, size_t i0, const uint256& h_sig);
uint256 PRF_rho(const uint252& phi, size_t i0, const uint256& h_sig);
#endif // _PRF_H_
#endif // ZC_PRF_H_

View File

@@ -1,5 +1,5 @@
#ifndef __ZCASH_UTIL_H
#define __ZCASH_UTIL_H
#ifndef ZC_UTIL_H_
#define ZC_UTIL_H_
#include <vector>
#include <cstdint>
@@ -8,4 +8,4 @@ std::vector<unsigned char> convertIntToVectorLE(const uint64_t val_int);
std::vector<bool> convertBytesVectorToVector(const std::vector<unsigned char>& bytes);
uint64_t convertVectorToInt(const std::vector<bool>& v);
#endif // __ZCASH_UTIL_H
#endif // ZC_UTIL_H_