Auto merge of #4654 - str4d:sodium-oxide, r=str4d
Replace most libsodium usage with Rust crates We currently use four components of libsodium: - Random byte generation - BLAKE2b - Ed25519 - ChaCha20Poly1305 This PR replaces the first three with equivalent logic from Rust crates: - `rand_core::OsRng` - `blake2b_simd` - `ed25519-zebra` - `libsodium` is still used for Ed25519 verification in the consensus rules until Canopy activation.
This commit is contained in:
commit
30619ae888
|
@ -15,7 +15,7 @@
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#include "librustzcash.h"
|
#include "librustzcash.h"
|
||||||
#include "sodium.h"
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
static void ECDSA(benchmark::State& state)
|
static void ECDSA(benchmark::State& state)
|
||||||
{
|
{
|
||||||
|
@ -75,20 +75,20 @@ static void ECDSA(benchmark::State& state)
|
||||||
|
|
||||||
static void JoinSplitSig(benchmark::State& state)
|
static void JoinSplitSig(benchmark::State& state)
|
||||||
{
|
{
|
||||||
uint256 joinSplitPubKey;
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
Ed25519SigningKey joinSplitPrivKey;
|
||||||
uint256 dataToBeSigned;
|
uint256 dataToBeSigned;
|
||||||
std::array<unsigned char, 64> joinSplitSig;
|
Ed25519Signature joinSplitSig;
|
||||||
|
|
||||||
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
|
ed25519_generate_keypair(&joinSplitPrivKey, &joinSplitPubKey);
|
||||||
crypto_sign_detached(&joinSplitSig[0], nullptr, dataToBeSigned.begin(), 32, joinSplitPrivKey);
|
ed25519_sign(&joinSplitPrivKey, dataToBeSigned.begin(), 32, &joinSplitSig);
|
||||||
|
|
||||||
while (state.KeepRunning()) {
|
while (state.KeepRunning()) {
|
||||||
// Declared with warn_unused_result.
|
// Declared with warn_unused_result.
|
||||||
auto res = crypto_sign_verify_detached(
|
auto res = ed25519_verify(
|
||||||
&joinSplitSig[0],
|
&joinSplitPubKey,
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitSig,
|
||||||
joinSplitPubKey.begin());
|
dataToBeSigned.begin(), 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "primitives/transaction.h"
|
#include "primitives/transaction.h"
|
||||||
|
@ -10,6 +9,7 @@
|
||||||
#include "zcash/JoinSplit.hpp"
|
#include "zcash/JoinSplit.hpp"
|
||||||
|
|
||||||
#include <librustzcash.h>
|
#include <librustzcash.h>
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
TEST(ChecktransactionTests, CheckVpubNotBothNonzero) {
|
TEST(ChecktransactionTests, CheckVpubNotBothNonzero) {
|
||||||
CMutableTransaction tx;
|
CMutableTransaction tx;
|
||||||
|
@ -92,10 +92,8 @@ CMutableTransaction GetValidTransaction(uint32_t consensusBranchId=SPROUT_BRANCH
|
||||||
|
|
||||||
void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranchId) {
|
void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranchId) {
|
||||||
// Generate an ephemeral keypair.
|
// Generate an ephemeral keypair.
|
||||||
uint256 joinSplitPubKey;
|
Ed25519SigningKey joinSplitPrivKey;
|
||||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
ed25519_generate_keypair(&joinSplitPrivKey, &mtx.joinSplitPubKey);
|
||||||
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
|
|
||||||
mtx.joinSplitPubKey = joinSplitPubKey;
|
|
||||||
|
|
||||||
// Compute the correct hSig.
|
// Compute the correct hSig.
|
||||||
// TODO: #966.
|
// TODO: #966.
|
||||||
|
@ -109,10 +107,10 @@ void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
assert(ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPrivKey,
|
||||||
joinSplitPrivKey
|
dataToBeSigned.begin(), 32,
|
||||||
) == 0);
|
&mtx.joinSplitSig));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ChecktransactionTests, ValidTransaction) {
|
TEST(ChecktransactionTests, ValidTransaction) {
|
||||||
|
@ -518,7 +516,7 @@ TEST(ChecktransactionTests, BadTxnsInvalidJoinsplitSignature) {
|
||||||
auto chainparams = Params();
|
auto chainparams = Params();
|
||||||
|
|
||||||
CMutableTransaction mtx = GetValidTransaction();
|
CMutableTransaction mtx = GetValidTransaction();
|
||||||
mtx.joinSplitSig[0] += 1;
|
mtx.joinSplitSig.bytes[0] += 1;
|
||||||
CTransaction tx(mtx);
|
CTransaction tx(mtx);
|
||||||
|
|
||||||
MockCValidationState state;
|
MockCValidationState state;
|
||||||
|
@ -607,8 +605,8 @@ TEST(ChecktransactionTests, NonCanonicalEd25519Signature) {
|
||||||
// Add L to S, which starts at mtx.joinSplitSig[32].
|
// Add L to S, which starts at mtx.joinSplitSig[32].
|
||||||
unsigned int s = 0;
|
unsigned int s = 0;
|
||||||
for (size_t i = 0; i < 32; i++) {
|
for (size_t i = 0; i < 32; i++) {
|
||||||
s = mtx.joinSplitSig[32 + i] + L[i] + (s >> 8);
|
s = mtx.joinSplitSig.bytes[32 + i] + L[i] + (s >> 8);
|
||||||
mtx.joinSplitSig[32 + i] = s & 0xff;
|
mtx.joinSplitSig.bytes[32 + i] = s & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction tx(mtx);
|
CTransaction tx(mtx);
|
||||||
|
@ -816,7 +814,7 @@ TEST(ChecktransactionTests, SaplingSproutInputSumsTooLarge) {
|
||||||
{
|
{
|
||||||
// create JSDescription
|
// create JSDescription
|
||||||
uint256 rt;
|
uint256 rt;
|
||||||
uint256 joinSplitPubKey;
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
||||||
libzcash::JSInput(),
|
libzcash::JSInput(),
|
||||||
libzcash::JSInput()
|
libzcash::JSInput()
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
using namespace libzcash;
|
using namespace libzcash;
|
||||||
|
|
||||||
// Make the Groth proof for a Sprout statement,
|
// Make the Groth proof for a Sprout statement,
|
||||||
|
@ -26,7 +28,7 @@ using namespace libzcash;
|
||||||
JSDescription makeSproutProof(
|
JSDescription makeSproutProof(
|
||||||
const std::array<JSInput, 2>& inputs,
|
const std::array<JSInput, 2>& inputs,
|
||||||
const std::array<JSOutput, 2>& outputs,
|
const std::array<JSOutput, 2>& outputs,
|
||||||
const uint256& joinSplitPubKey,
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
uint64_t vpub_old,
|
uint64_t vpub_old,
|
||||||
uint64_t vpub_new,
|
uint64_t vpub_new,
|
||||||
const uint256& rt
|
const uint256& rt
|
||||||
|
@ -36,7 +38,7 @@ JSDescription makeSproutProof(
|
||||||
|
|
||||||
bool verifySproutProof(
|
bool verifySproutProof(
|
||||||
const JSDescription& jsdesc,
|
const JSDescription& jsdesc,
|
||||||
const uint256& joinSplitPubKey
|
const Ed25519VerificationKey& joinSplitPubKey
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto verifier = ProofVerifier::Strict();
|
auto verifier = ProofVerifier::Strict();
|
||||||
|
@ -59,7 +61,8 @@ void test_full_api()
|
||||||
// Set up a JoinSplit description
|
// Set up a JoinSplit description
|
||||||
uint64_t vpub_old = 10;
|
uint64_t vpub_old = 10;
|
||||||
uint64_t vpub_new = 0;
|
uint64_t vpub_new = 0;
|
||||||
uint256 joinSplitPubKey = random_uint256();
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
|
GetRandBytes(joinSplitPubKey.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||||
uint256 rt = tree.root();
|
uint256 rt = tree.root();
|
||||||
JSDescription jsdesc;
|
JSDescription jsdesc;
|
||||||
|
|
||||||
|
@ -118,7 +121,8 @@ void test_full_api()
|
||||||
vpub_old = 0;
|
vpub_old = 0;
|
||||||
vpub_new = 1;
|
vpub_new = 1;
|
||||||
rt = tree.root();
|
rt = tree.root();
|
||||||
auto joinSplitPubKey2 = random_uint256();
|
Ed25519VerificationKey joinSplitPubKey2;
|
||||||
|
GetRandBytes(joinSplitPubKey2.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||||
|
|
||||||
{
|
{
|
||||||
std::array<JSInput, 2> inputs = {
|
std::array<JSInput, 2> inputs = {
|
||||||
|
@ -166,7 +170,8 @@ void invokeAPI(
|
||||||
) {
|
) {
|
||||||
uint256 ephemeralKey;
|
uint256 ephemeralKey;
|
||||||
uint256 randomSeed;
|
uint256 randomSeed;
|
||||||
uint256 joinSplitPubKey = random_uint256();
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
|
GetRandBytes(joinSplitPubKey.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||||
std::array<uint256, 2> macs;
|
std::array<uint256, 2> macs;
|
||||||
std::array<uint256, 2> nullifiers;
|
std::array<uint256, 2> nullifiers;
|
||||||
std::array<uint256, 2> commitments;
|
std::array<uint256, 2> commitments;
|
||||||
|
@ -277,10 +282,13 @@ for test_input in TEST_VECTORS:
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOST_FOREACH(std::vector<std::string>& v, tests) {
|
BOOST_FOREACH(std::vector<std::string>& v, tests) {
|
||||||
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
|
auto pubKeyBytes = uint256S(v[3]);
|
||||||
|
std::copy(pubKeyBytes.begin(), pubKeyBytes.end(), joinSplitPubKey.bytes);
|
||||||
auto expected = ZCJoinSplit::h_sig(
|
auto expected = ZCJoinSplit::h_sig(
|
||||||
uint256S(v[0]),
|
uint256S(v[0]),
|
||||||
{uint256S(v[1]), uint256S(v[2])},
|
{uint256S(v[1]), uint256S(v[2])},
|
||||||
uint256S(v[3])
|
joinSplitPubKey
|
||||||
);
|
);
|
||||||
|
|
||||||
EXPECT_EQ(expected, uint256S(v[4]));
|
EXPECT_EQ(expected, uint256S(v[4]));
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
TEST(Transaction, JSDescriptionRandomized) {
|
TEST(Transaction, JSDescriptionRandomized) {
|
||||||
// construct a merkle tree
|
// construct a merkle tree
|
||||||
SproutMerkleTree merkleTree;
|
SproutMerkleTree merkleTree;
|
||||||
|
@ -28,7 +30,7 @@ TEST(Transaction, JSDescriptionRandomized) {
|
||||||
auto witness = merkleTree.witness();
|
auto witness = merkleTree.witness();
|
||||||
|
|
||||||
// create JSDescription
|
// create JSDescription
|
||||||
uint256 joinSplitPubKey;
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
||||||
libzcash::JSInput(witness, note, k),
|
libzcash::JSInput(witness, note, k),
|
||||||
libzcash::JSInput() // dummy input of zero value
|
libzcash::JSInput() // dummy input of zero value
|
||||||
|
|
|
@ -1052,18 +1052,18 @@ bool ContextualCheckTransaction(
|
||||||
|
|
||||||
// We rely on libsodium to check that the signature is canonical.
|
// We rely on libsodium to check that the signature is canonical.
|
||||||
// https://github.com/jedisct1/libsodium/commit/62911edb7ff2275cccd74bf1c8aefcc4d76924e0
|
// https://github.com/jedisct1/libsodium/commit/62911edb7ff2275cccd74bf1c8aefcc4d76924e0
|
||||||
if (ed25519_verifier(&tx.joinSplitSig[0],
|
if (ed25519_verifier(tx.joinSplitSig.bytes,
|
||||||
dataToBeSigned.begin(), 32,
|
dataToBeSigned.begin(), 32,
|
||||||
tx.joinSplitPubKey.begin()
|
tx.joinSplitPubKey.bytes
|
||||||
) != 0) {
|
) != 0) {
|
||||||
// Check whether the failure was caused by an outdated consensus
|
// Check whether the failure was caused by an outdated consensus
|
||||||
// branch ID; if so, inform the node that they need to upgrade. We
|
// branch ID; if so, inform the node that they need to upgrade. We
|
||||||
// only check the previous epoch's branch ID, on the assumption that
|
// only check the previous epoch's branch ID, on the assumption that
|
||||||
// users creating transactions will notice their transactions
|
// users creating transactions will notice their transactions
|
||||||
// failing before a second network upgrade occurs.
|
// failing before a second network upgrade occurs.
|
||||||
if (ed25519_verifier(&tx.joinSplitSig[0],
|
if (ed25519_verifier(tx.joinSplitSig.bytes,
|
||||||
prevDataToBeSigned.begin(), 32,
|
prevDataToBeSigned.begin(), 32,
|
||||||
tx.joinSplitPubKey.begin()
|
tx.joinSplitPubKey.bytes
|
||||||
) == 0) {
|
) == 0) {
|
||||||
return state.DoS(
|
return state.DoS(
|
||||||
dosLevelPotentiallyRelaxing, false, REJECT_INVALID, strprintf(
|
dosLevelPotentiallyRelaxing, false, REJECT_INVALID, strprintf(
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "utilstrencodings.h"
|
#include "utilstrencodings.h"
|
||||||
|
|
||||||
JSDescription::JSDescription(
|
JSDescription::JSDescription(
|
||||||
const uint256& joinSplitPubKey,
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
const uint256& anchor,
|
const uint256& anchor,
|
||||||
const std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
const std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
||||||
const std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
const std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
||||||
|
@ -42,7 +42,7 @@ JSDescription::JSDescription(
|
||||||
}
|
}
|
||||||
|
|
||||||
JSDescription JSDescription::Randomized(
|
JSDescription JSDescription::Randomized(
|
||||||
const uint256& joinSplitPubKey,
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
const uint256& anchor,
|
const uint256& anchor,
|
||||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
||||||
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
||||||
|
@ -71,7 +71,7 @@ JSDescription JSDescription::Randomized(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 JSDescription::h_sig(const uint256& joinSplitPubKey) const
|
uint256 JSDescription::h_sig(const Ed25519VerificationKey& joinSplitPubKey) const
|
||||||
{
|
{
|
||||||
return ZCJoinSplit::h_sig(randomSeed, nullifiers, joinSplitPubKey);
|
return ZCJoinSplit::h_sig(randomSeed, nullifiers, joinSplitPubKey);
|
||||||
}
|
}
|
||||||
|
@ -197,8 +197,8 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
|
||||||
*const_cast<std::vector<SpendDescription>*>(&vShieldedSpend) = tx.vShieldedSpend;
|
*const_cast<std::vector<SpendDescription>*>(&vShieldedSpend) = tx.vShieldedSpend;
|
||||||
*const_cast<std::vector<OutputDescription>*>(&vShieldedOutput) = tx.vShieldedOutput;
|
*const_cast<std::vector<OutputDescription>*>(&vShieldedOutput) = tx.vShieldedOutput;
|
||||||
*const_cast<std::vector<JSDescription>*>(&vJoinSplit) = tx.vJoinSplit;
|
*const_cast<std::vector<JSDescription>*>(&vJoinSplit) = tx.vJoinSplit;
|
||||||
*const_cast<uint256*>(&joinSplitPubKey) = tx.joinSplitPubKey;
|
*const_cast<Ed25519VerificationKey*>(&joinSplitPubKey) = tx.joinSplitPubKey;
|
||||||
*const_cast<joinsplit_sig_t*>(&joinSplitSig) = tx.joinSplitSig;
|
*const_cast<Ed25519Signature*>(&joinSplitSig) = tx.joinSplitSig;
|
||||||
*const_cast<binding_sig_t*>(&bindingSig) = tx.bindingSig;
|
*const_cast<binding_sig_t*>(&bindingSig) = tx.bindingSig;
|
||||||
*const_cast<uint256*>(&hash) = tx.hash;
|
*const_cast<uint256*>(&hash) = tx.hash;
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "zcash/JoinSplit.hpp"
|
#include "zcash/JoinSplit.hpp"
|
||||||
#include "zcash/Proof.hpp"
|
#include "zcash/Proof.hpp"
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
// Overwinter transaction version
|
// Overwinter transaction version
|
||||||
static const int32_t OVERWINTER_TX_VERSION = 3;
|
static const int32_t OVERWINTER_TX_VERSION = 3;
|
||||||
static_assert(OVERWINTER_TX_VERSION >= OVERWINTER_MIN_TX_VERSION,
|
static_assert(OVERWINTER_TX_VERSION >= OVERWINTER_MIN_TX_VERSION,
|
||||||
|
@ -235,7 +237,7 @@ public:
|
||||||
JSDescription(): vpub_old(0), vpub_new(0) { }
|
JSDescription(): vpub_old(0), vpub_new(0) { }
|
||||||
|
|
||||||
JSDescription(
|
JSDescription(
|
||||||
const uint256& joinSplitPubKey,
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
const uint256& rt,
|
const uint256& rt,
|
||||||
const std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
const std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
||||||
const std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
const std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
||||||
|
@ -246,7 +248,7 @@ public:
|
||||||
);
|
);
|
||||||
|
|
||||||
static JSDescription Randomized(
|
static JSDescription Randomized(
|
||||||
const uint256& joinSplitPubKey,
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
const uint256& rt,
|
const uint256& rt,
|
||||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
||||||
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
||||||
|
@ -260,7 +262,7 @@ public:
|
||||||
);
|
);
|
||||||
|
|
||||||
// Returns the calculated h_sig
|
// Returns the calculated h_sig
|
||||||
uint256 h_sig(const uint256& joinSplitPubKey) const;
|
uint256 h_sig(const Ed25519VerificationKey& joinSplitPubKey) const;
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
@ -553,8 +555,8 @@ public:
|
||||||
const std::vector<SpendDescription> vShieldedSpend;
|
const std::vector<SpendDescription> vShieldedSpend;
|
||||||
const std::vector<OutputDescription> vShieldedOutput;
|
const std::vector<OutputDescription> vShieldedOutput;
|
||||||
const std::vector<JSDescription> vJoinSplit;
|
const std::vector<JSDescription> vJoinSplit;
|
||||||
const uint256 joinSplitPubKey;
|
const Ed25519VerificationKey joinSplitPubKey;
|
||||||
const joinsplit_sig_t joinSplitSig = {{0}};
|
const Ed25519Signature joinSplitSig;
|
||||||
const binding_sig_t bindingSig = {{0}};
|
const binding_sig_t bindingSig = {{0}};
|
||||||
|
|
||||||
/** Construct a CTransaction that qualifies as IsNull() */
|
/** Construct a CTransaction that qualifies as IsNull() */
|
||||||
|
@ -611,8 +613,8 @@ public:
|
||||||
auto os = WithVersion(&s, static_cast<int>(header));
|
auto os = WithVersion(&s, static_cast<int>(header));
|
||||||
::SerReadWrite(os, *const_cast<std::vector<JSDescription>*>(&vJoinSplit), ser_action);
|
::SerReadWrite(os, *const_cast<std::vector<JSDescription>*>(&vJoinSplit), ser_action);
|
||||||
if (vJoinSplit.size() > 0) {
|
if (vJoinSplit.size() > 0) {
|
||||||
READWRITE(*const_cast<uint256*>(&joinSplitPubKey));
|
READWRITE(*const_cast<Ed25519VerificationKey*>(&joinSplitPubKey));
|
||||||
READWRITE(*const_cast<joinsplit_sig_t*>(&joinSplitSig));
|
READWRITE(*const_cast<Ed25519Signature*>(&joinSplitSig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isSaplingV4 && !(vShieldedSpend.empty() && vShieldedOutput.empty())) {
|
if (isSaplingV4 && !(vShieldedSpend.empty() && vShieldedOutput.empty())) {
|
||||||
|
@ -700,8 +702,8 @@ struct CMutableTransaction
|
||||||
std::vector<SpendDescription> vShieldedSpend;
|
std::vector<SpendDescription> vShieldedSpend;
|
||||||
std::vector<OutputDescription> vShieldedOutput;
|
std::vector<OutputDescription> vShieldedOutput;
|
||||||
std::vector<JSDescription> vJoinSplit;
|
std::vector<JSDescription> vJoinSplit;
|
||||||
uint256 joinSplitPubKey;
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
CTransaction::joinsplit_sig_t joinSplitSig = {{0}};
|
Ed25519Signature joinSplitSig;
|
||||||
CTransaction::binding_sig_t bindingSig = {{0}};
|
CTransaction::binding_sig_t bindingSig = {{0}};
|
||||||
|
|
||||||
CMutableTransaction();
|
CMutableTransaction();
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
class SproutProofVerifier : public boost::static_visitor<bool>
|
class SproutProofVerifier : public boost::static_visitor<bool>
|
||||||
{
|
{
|
||||||
ProofVerifier& verifier;
|
ProofVerifier& verifier;
|
||||||
const uint256& joinSplitPubKey;
|
const Ed25519VerificationKey& joinSplitPubKey;
|
||||||
const JSDescription& jsdesc;
|
const JSDescription& jsdesc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SproutProofVerifier(
|
SproutProofVerifier(
|
||||||
ProofVerifier& verifier,
|
ProofVerifier& verifier,
|
||||||
const uint256& joinSplitPubKey,
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
const JSDescription& jsdesc
|
const JSDescription& jsdesc
|
||||||
) : jsdesc(jsdesc), verifier(verifier), joinSplitPubKey(joinSplitPubKey) {}
|
) : jsdesc(jsdesc), verifier(verifier), joinSplitPubKey(joinSplitPubKey) {}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ ProofVerifier ProofVerifier::Disabled() {
|
||||||
|
|
||||||
bool ProofVerifier::VerifySprout(
|
bool ProofVerifier::VerifySprout(
|
||||||
const JSDescription& jsdesc,
|
const JSDescription& jsdesc,
|
||||||
const uint256& joinSplitPubKey
|
const Ed25519VerificationKey& joinSplitPubKey
|
||||||
) {
|
) {
|
||||||
if (!perform_verification) {
|
if (!perform_verification) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
class ProofVerifier {
|
class ProofVerifier {
|
||||||
private:
|
private:
|
||||||
bool perform_verification;
|
bool perform_verification;
|
||||||
|
@ -33,7 +35,7 @@ public:
|
||||||
// Verifies that the JoinSplit proof is correct.
|
// Verifies that the JoinSplit proof is correct.
|
||||||
bool VerifySprout(
|
bool VerifySprout(
|
||||||
const JSDescription& jsdesc,
|
const JSDescription& jsdesc,
|
||||||
const uint256& joinSplitPubKey
|
const Ed25519VerificationKey& joinSplitPubKey
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sodium.h"
|
#include <librustzcash.h>
|
||||||
|
|
||||||
static inline int64_t GetPerformanceCounter()
|
static inline int64_t GetPerformanceCounter()
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ static inline int64_t GetPerformanceCounter()
|
||||||
|
|
||||||
void GetRandBytes(unsigned char* buf, size_t num)
|
void GetRandBytes(unsigned char* buf, size_t num)
|
||||||
{
|
{
|
||||||
randombytes_buf(buf, num);
|
librustzcash_getrandom(buf, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GetRand(uint64_t nMax)
|
uint64_t GetRand(uint64_t nMax)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions to gather random data via the libsodium CSPRNG
|
* Functions to gather random data via the rand_core OsRng
|
||||||
*/
|
*/
|
||||||
void GetRandBytes(unsigned char* buf, size_t num);
|
void GetRandBytes(unsigned char* buf, size_t num);
|
||||||
uint64_t GetRand(uint64_t nMax);
|
uint64_t GetRand(uint64_t nMax);
|
||||||
|
|
|
@ -235,8 +235,16 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tx.nVersion >= 2 && tx.vJoinSplit.size() > 0) {
|
if (tx.nVersion >= 2 && tx.vJoinSplit.size() > 0) {
|
||||||
entry.pushKV("joinSplitPubKey", tx.joinSplitPubKey.GetHex());
|
// Copy joinSplitPubKey into a uint256 so that
|
||||||
entry.pushKV("joinSplitSig", HexStr(tx.joinSplitSig.begin(), tx.joinSplitSig.end()));
|
// it is byte-flipped in the RPC output.
|
||||||
|
uint256 joinSplitPubKey;
|
||||||
|
std::copy(
|
||||||
|
tx.joinSplitPubKey.bytes,
|
||||||
|
tx.joinSplitPubKey.bytes + ED25519_VERIFICATION_KEY_LEN,
|
||||||
|
joinSplitPubKey.begin());
|
||||||
|
entry.pushKV("joinSplitPubKey", joinSplitPubKey.GetHex());
|
||||||
|
entry.pushKV("joinSplitSig",
|
||||||
|
HexStr(tx.joinSplitSig.bytes, tx.joinSplitSig.bytes + ED25519_SIGNATURE_LEN));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hashBlock.IsNull()) {
|
if (!hashBlock.IsNull()) {
|
||||||
|
|
|
@ -359,6 +359,15 @@ extern "C" {
|
||||||
unsigned char *h_ret
|
unsigned char *h_ret
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Fills the provided buffer with random bytes. This is intended to
|
||||||
|
/// be a cryptographically secure RNG; it uses Rust's `OsRng`, which
|
||||||
|
/// is implemented in terms of the `getrandom` crate. The first call
|
||||||
|
/// to this function may block until sufficient randomness is available.
|
||||||
|
void librustzcash_getrandom(
|
||||||
|
unsigned char *buf,
|
||||||
|
size_t buf_len
|
||||||
|
);
|
||||||
|
|
||||||
int librustzcash_zebra_crypto_sign_verify_detached(
|
int librustzcash_zebra_crypto_sign_verify_detached(
|
||||||
const unsigned char *sig,
|
const unsigned char *sig,
|
||||||
const unsigned char *m,
|
const unsigned char *m,
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright (c) 2020 The Zcash developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||||
|
|
||||||
|
#ifndef ED25519_INCLUDE_H_
|
||||||
|
#define ED25519_INCLUDE_H_
|
||||||
|
|
||||||
|
#include "ed25519/types.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdalign.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Generates a new Ed25519 keypair.
|
||||||
|
void ed25519_generate_keypair(
|
||||||
|
Ed25519SigningKey* sk,
|
||||||
|
Ed25519VerificationKey* vk);
|
||||||
|
|
||||||
|
/// Creates a signature on msg using the given signing key.
|
||||||
|
bool ed25519_sign(
|
||||||
|
const Ed25519SigningKey* sk,
|
||||||
|
const unsigned char* msg,
|
||||||
|
size_t msglen,
|
||||||
|
Ed25519Signature* signature);
|
||||||
|
|
||||||
|
/// Verifies a purported `signature` on the given `msg`.
|
||||||
|
///
|
||||||
|
/// # Zcash-specific consensus properties
|
||||||
|
///
|
||||||
|
/// Ed25519 checks are described in §5.4.5 of the Zcash protocol specification
|
||||||
|
/// and in ZIP 215. The verification criteria for an (encoded) `signature`
|
||||||
|
/// (`R_bytes`, `s_bytes`) with (encoded) verification key `A_bytes` are:
|
||||||
|
///
|
||||||
|
/// - `A_bytes` and `R_bytes` MUST be encodings of points `A` and `R`
|
||||||
|
/// respectively on the twisted Edwards form of Curve25519, and non-canonical
|
||||||
|
/// encodings MUST be accepted;
|
||||||
|
/// - `s_bytes` MUST represent an integer `s` less than `l`, the order of the
|
||||||
|
/// prime-order subgroup of Curve25519;
|
||||||
|
/// - the verification equation `[8][s]B = [8]R + [8][k]A` MUST be satisfied;
|
||||||
|
/// - the alternate verification equation `[s]B = R + [k]A`, allowed by RFC 8032,
|
||||||
|
/// MUST NOT be used.
|
||||||
|
bool ed25519_verify(
|
||||||
|
const Ed25519VerificationKey* vk,
|
||||||
|
const Ed25519Signature* signature,
|
||||||
|
const unsigned char* msg,
|
||||||
|
size_t msglen);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ED25519_INCLUDE_H_
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright (c) 2020 The Zcash developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||||
|
|
||||||
|
#ifndef RUST_ED25519_TYPES_H_
|
||||||
|
#define RUST_ED25519_TYPES_H_
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdalign.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ED25519_SIGNING_KEY_LEN 32U
|
||||||
|
#define ED25519_VERIFICATION_KEY_LEN 32U
|
||||||
|
#define ED25519_SIGNATURE_LEN 64U
|
||||||
|
|
||||||
|
/// An Ed25519 signing key.
|
||||||
|
///
|
||||||
|
/// This is also called a secret key by other implementations.
|
||||||
|
typedef struct Ed25519SigningKey {
|
||||||
|
unsigned char bytes[ED25519_SIGNING_KEY_LEN];
|
||||||
|
} Ed25519SigningKey;
|
||||||
|
static_assert(
|
||||||
|
sizeof(Ed25519SigningKey) == ED25519_SIGNING_KEY_LEN,
|
||||||
|
"Ed25519SigningKey struct is not the same size as the underlying byte array");
|
||||||
|
static_assert(
|
||||||
|
alignof(Ed25519SigningKey) == 1,
|
||||||
|
"Ed25519SigningKey struct alignment is not 1");
|
||||||
|
|
||||||
|
/// An encoded Ed25519 verification key.
|
||||||
|
///
|
||||||
|
/// This is also called a public key by other implementations.
|
||||||
|
///
|
||||||
|
/// This type does not guarantee validity of the verification key.
|
||||||
|
typedef struct Ed25519VerificationKey {
|
||||||
|
unsigned char bytes[ED25519_VERIFICATION_KEY_LEN];
|
||||||
|
} Ed25519VerificationKey;
|
||||||
|
static_assert(
|
||||||
|
sizeof(Ed25519VerificationKey) == ED25519_VERIFICATION_KEY_LEN,
|
||||||
|
"Ed25519VerificationKey struct is not the same size as the underlying byte array");
|
||||||
|
static_assert(
|
||||||
|
alignof(Ed25519VerificationKey) == 1,
|
||||||
|
"Ed25519VerificationKey struct alignment is not 1");
|
||||||
|
|
||||||
|
/// An Ed25519 signature.
|
||||||
|
typedef struct Ed25519Signature {
|
||||||
|
unsigned char bytes[ED25519_SIGNATURE_LEN];
|
||||||
|
} Ed25519Signature;
|
||||||
|
static_assert(
|
||||||
|
sizeof(Ed25519Signature) == ED25519_SIGNATURE_LEN,
|
||||||
|
"Ed25519Signature struct is not the same size as the underlying byte array");
|
||||||
|
static_assert(
|
||||||
|
alignof(Ed25519Signature) == 1,
|
||||||
|
"Ed25519Signature struct alignment is not 1");
|
||||||
|
|
||||||
|
#endif // RUST_ED25519_TYPES_H_
|
|
@ -0,0 +1,67 @@
|
||||||
|
// Copyright (c) 2020 The Zcash developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||||
|
|
||||||
|
use ed25519_zebra::{Signature, SigningKey, VerificationKey};
|
||||||
|
use libc::{c_uchar, size_t};
|
||||||
|
use rand_core::OsRng;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn ed25519_generate_keypair(sk: *mut [u8; 32], vk: *mut [u8; 32]) {
|
||||||
|
let sk = unsafe { sk.as_mut() }.unwrap();
|
||||||
|
let vk = unsafe { vk.as_mut() }.unwrap();
|
||||||
|
|
||||||
|
let signing_key = SigningKey::new(OsRng);
|
||||||
|
|
||||||
|
*sk = signing_key.into();
|
||||||
|
*vk = VerificationKey::from(&signing_key).into();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn ed25519_sign(
|
||||||
|
sk: *const [u8; 32],
|
||||||
|
msg: *const c_uchar,
|
||||||
|
msg_len: size_t,
|
||||||
|
signature: *mut [u8; 64],
|
||||||
|
) -> bool {
|
||||||
|
let sk = SigningKey::from(*unsafe { sk.as_ref() }.unwrap());
|
||||||
|
|
||||||
|
let msg = unsafe { slice::from_raw_parts(msg, msg_len) };
|
||||||
|
|
||||||
|
let signature = unsafe {
|
||||||
|
match signature.as_mut() {
|
||||||
|
Some(sig) => sig,
|
||||||
|
None => return false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
*signature = sk.sign(msg).into();
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn ed25519_verify(
|
||||||
|
vk: *const [u8; 32],
|
||||||
|
signature: *const [u8; 64],
|
||||||
|
msg: *const c_uchar,
|
||||||
|
msg_len: size_t,
|
||||||
|
) -> bool {
|
||||||
|
let vk = match VerificationKey::try_from(*unsafe { vk.as_ref() }.unwrap()) {
|
||||||
|
Ok(vk) => vk,
|
||||||
|
Err(_) => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let signature = Signature::from(*unsafe {
|
||||||
|
match signature.as_ref() {
|
||||||
|
Some(sig) => sig,
|
||||||
|
None => return false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let msg = unsafe { slice::from_raw_parts(msg, msg_len) };
|
||||||
|
|
||||||
|
vk.verify(&signature, msg).is_ok()
|
||||||
|
}
|
|
@ -67,6 +67,7 @@ use zcash_proofs::{
|
||||||
|
|
||||||
use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree};
|
use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree};
|
||||||
|
|
||||||
|
mod ed25519;
|
||||||
mod tracing_ffi;
|
mod tracing_ffi;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1343,6 +1344,12 @@ pub extern "system" fn librustzcash_mmr_hash_node(
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn librustzcash_getrandom(buf: *mut u8, buf_len: usize) {
|
||||||
|
let buf = unsafe { slice::from_raw_parts_mut(buf, buf_len) };
|
||||||
|
OsRng.fill_bytes(buf);
|
||||||
|
}
|
||||||
|
|
||||||
// The `librustzcash_zebra_crypto_sign_verify_detached` API attempts to
|
// The `librustzcash_zebra_crypto_sign_verify_detached` API attempts to
|
||||||
// mimic the `crypto_sign_verify_detached` API in libsodium, but uses
|
// mimic the `crypto_sign_verify_detached` API in libsodium, but uses
|
||||||
// the ed25519-zebra crate internally instead.
|
// the ed25519-zebra crate internally instead.
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
#include "prevector.h"
|
#include "prevector.h"
|
||||||
|
|
||||||
static const unsigned int MAX_SIZE = 0x02000000;
|
static const unsigned int MAX_SIZE = 0x02000000;
|
||||||
|
@ -581,6 +583,24 @@ template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_p
|
||||||
template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
|
template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
|
||||||
template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
|
template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ed25519SigningKey
|
||||||
|
*/
|
||||||
|
template<typename Stream> void Serialize(Stream& os, const Ed25519SigningKey& item);
|
||||||
|
template<typename Stream> void Unserialize(Stream& is, Ed25519SigningKey& item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ed25519VerificationKey
|
||||||
|
*/
|
||||||
|
template<typename Stream> void Serialize(Stream& os, const Ed25519VerificationKey& item);
|
||||||
|
template<typename Stream> void Unserialize(Stream& is, Ed25519VerificationKey& item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ed25519Signature
|
||||||
|
*/
|
||||||
|
template<typename Stream> void Serialize(Stream& os, const Ed25519Signature& item);
|
||||||
|
template<typename Stream> void Unserialize(Stream& is, Ed25519Signature& item);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -951,6 +971,57 @@ void Unserialize(Stream& is, std::shared_ptr<const T>& p)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ed25519SigningKey
|
||||||
|
*/
|
||||||
|
template<typename Stream>
|
||||||
|
void Serialize(Stream& os, const Ed25519SigningKey& sk)
|
||||||
|
{
|
||||||
|
os.write((char*)sk.bytes, ED25519_SIGNING_KEY_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream>
|
||||||
|
void Unserialize(Stream& is, Ed25519SigningKey& sk)
|
||||||
|
{
|
||||||
|
is.read((char*)sk.bytes, ED25519_SIGNING_KEY_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ed25519VerificationKey
|
||||||
|
*/
|
||||||
|
template<typename Stream>
|
||||||
|
void Serialize(Stream& os, const Ed25519VerificationKey& vk)
|
||||||
|
{
|
||||||
|
os.write((char*)vk.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream>
|
||||||
|
void Unserialize(Stream& is, Ed25519VerificationKey& vk)
|
||||||
|
{
|
||||||
|
is.read((char*)vk.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ed25519Signature
|
||||||
|
*/
|
||||||
|
template<typename Stream>
|
||||||
|
void Serialize(Stream& os, const Ed25519Signature& sig)
|
||||||
|
{
|
||||||
|
os.write((char*)sig.bytes, ED25519_SIGNATURE_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream>
|
||||||
|
void Unserialize(Stream& is, Ed25519Signature& sig)
|
||||||
|
{
|
||||||
|
is.read((char*)sig.bytes, ED25519_SIGNATURE_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for ADD_SERIALIZE_METHODS and READWRITE macro
|
* Support for ADD_SERIALIZE_METHODS and READWRITE macro
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,13 +14,14 @@
|
||||||
#include "test/test_util.h"
|
#include "test/test_util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "sodium.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
// Old script.cpp SignatureHash function
|
// Old script.cpp SignatureHash function
|
||||||
|
@ -77,7 +78,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blank out the joinsplit signature.
|
// Blank out the joinsplit signature.
|
||||||
memset(&txTmp.joinSplitSig[0], 0, txTmp.joinSplitSig.size());
|
memset(&txTmp.joinSplitSig.bytes, 0, ED25519_SIGNATURE_LEN);
|
||||||
|
|
||||||
// Serialize and hash
|
// Serialize and hash
|
||||||
CHashWriter ss(SER_GETHASH, 0);
|
CHashWriter ss(SER_GETHASH, 0);
|
||||||
|
@ -152,7 +153,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co
|
||||||
sdesc.anchor = GetRandHash();
|
sdesc.anchor = GetRandHash();
|
||||||
sdesc.nullifier = GetRandHash();
|
sdesc.nullifier = GetRandHash();
|
||||||
sdesc.rk = GetRandHash();
|
sdesc.rk = GetRandHash();
|
||||||
randombytes_buf(sdesc.zkproof.begin(), sdesc.zkproof.size());
|
GetRandBytes(sdesc.zkproof.begin(), sdesc.zkproof.size());
|
||||||
tx.vShieldedSpend.push_back(sdesc);
|
tx.vShieldedSpend.push_back(sdesc);
|
||||||
}
|
}
|
||||||
for (int out = 0; out < shielded_outs; out++) {
|
for (int out = 0; out < shielded_outs; out++) {
|
||||||
|
@ -160,9 +161,9 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co
|
||||||
odesc.cv = GetRandHash();
|
odesc.cv = GetRandHash();
|
||||||
odesc.cmu = GetRandHash();
|
odesc.cmu = GetRandHash();
|
||||||
odesc.ephemeralKey = GetRandHash();
|
odesc.ephemeralKey = GetRandHash();
|
||||||
randombytes_buf(odesc.encCiphertext.begin(), odesc.encCiphertext.size());
|
GetRandBytes(odesc.encCiphertext.begin(), odesc.encCiphertext.size());
|
||||||
randombytes_buf(odesc.outCiphertext.begin(), odesc.outCiphertext.size());
|
GetRandBytes(odesc.outCiphertext.begin(), odesc.outCiphertext.size());
|
||||||
randombytes_buf(odesc.zkproof.begin(), odesc.zkproof.size());
|
GetRandBytes(odesc.zkproof.begin(), odesc.zkproof.size());
|
||||||
tx.vShieldedOutput.push_back(odesc);
|
tx.vShieldedOutput.push_back(odesc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,11 +182,11 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co
|
||||||
jsdesc.nullifiers[1] = GetRandHash();
|
jsdesc.nullifiers[1] = GetRandHash();
|
||||||
jsdesc.ephemeralKey = GetRandHash();
|
jsdesc.ephemeralKey = GetRandHash();
|
||||||
jsdesc.randomSeed = GetRandHash();
|
jsdesc.randomSeed = GetRandHash();
|
||||||
randombytes_buf(jsdesc.ciphertexts[0].begin(), jsdesc.ciphertexts[0].size());
|
GetRandBytes(jsdesc.ciphertexts[0].begin(), jsdesc.ciphertexts[0].size());
|
||||||
randombytes_buf(jsdesc.ciphertexts[1].begin(), jsdesc.ciphertexts[1].size());
|
GetRandBytes(jsdesc.ciphertexts[1].begin(), jsdesc.ciphertexts[1].size());
|
||||||
{
|
{
|
||||||
libzcash::GrothProof zkproof;
|
libzcash::GrothProof zkproof;
|
||||||
randombytes_buf(zkproof.begin(), zkproof.size());
|
GetRandBytes(zkproof.begin(), zkproof.size());
|
||||||
jsdesc.proof = zkproof;
|
jsdesc.proof = zkproof;
|
||||||
}
|
}
|
||||||
jsdesc.macs[0] = GetRandHash();
|
jsdesc.macs[0] = GetRandHash();
|
||||||
|
@ -194,18 +195,18 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co
|
||||||
tx.vJoinSplit.push_back(jsdesc);
|
tx.vJoinSplit.push_back(jsdesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
Ed25519SigningKey joinSplitPrivKey;
|
||||||
crypto_sign_keypair(tx.joinSplitPubKey.begin(), joinSplitPrivKey);
|
ed25519_generate_keypair(&joinSplitPrivKey, &tx.joinSplitPubKey);
|
||||||
|
|
||||||
// Empty output script.
|
// Empty output script.
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
CTransaction signTx(tx);
|
CTransaction signTx(tx);
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||||
|
|
||||||
assert(crypto_sign_detached(&tx.joinSplitSig[0], NULL,
|
assert(ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPrivKey,
|
||||||
joinSplitPrivKey
|
dataToBeSigned.begin(), 32,
|
||||||
) == 0);
|
&tx.joinSplitSig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
#include "test/test_util.h"
|
#include "test/test_util.h"
|
||||||
#include "primitives/transaction.h"
|
#include "primitives/transaction.h"
|
||||||
|
|
||||||
#include "sodium.h"
|
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -33,6 +31,8 @@
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include <boost/test/data/test_case.hpp>
|
#include <boost/test/data/test_case.hpp>
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
#include "zcash/Note.hpp"
|
#include "zcash/Note.hpp"
|
||||||
|
@ -308,7 +308,7 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
|
||||||
auto witness = merkleTree.witness();
|
auto witness = merkleTree.witness();
|
||||||
|
|
||||||
// create JSDescription
|
// create JSDescription
|
||||||
uint256 joinSplitPubKey;
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
||||||
libzcash::JSInput(witness, note, k),
|
libzcash::JSInput(witness, note, k),
|
||||||
libzcash::JSInput() // dummy input of zero value
|
libzcash::JSInput() // dummy input of zero value
|
||||||
|
@ -416,8 +416,8 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa
|
||||||
CMutableTransaction newTx(tx);
|
CMutableTransaction newTx(tx);
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
|
|
||||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
Ed25519SigningKey joinSplitPrivKey;
|
||||||
crypto_sign_keypair(newTx.joinSplitPubKey.begin(), joinSplitPrivKey);
|
ed25519_generate_keypair(&joinSplitPrivKey, &newTx.joinSplitPubKey);
|
||||||
|
|
||||||
// No joinsplits, vin and vout, means it should be invalid.
|
// No joinsplits, vin and vout, means it should be invalid.
|
||||||
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
|
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
|
||||||
|
@ -443,10 +443,10 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa
|
||||||
CTransaction signTx(newTx);
|
CTransaction signTx(newTx);
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||||
|
|
||||||
assert(crypto_sign_detached(&newTx.joinSplitSig[0], NULL,
|
assert(ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPrivKey,
|
||||||
joinSplitPrivKey
|
dataToBeSigned.begin(), 32,
|
||||||
) == 0);
|
&newTx.joinSplitSig));
|
||||||
|
|
||||||
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
||||||
BOOST_CHECK(ContextualCheckTransaction(newTx, state, Params(), 0, true));
|
BOOST_CHECK(ContextualCheckTransaction(newTx, state, Params(), 0, true));
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
#include <librustzcash.h>
|
#include <librustzcash.h>
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
SpendDescriptionInfo::SpendDescriptionInfo(
|
SpendDescriptionInfo::SpendDescriptionInfo(
|
||||||
libzcash::SaplingExpandedSpendingKey expsk,
|
libzcash::SaplingExpandedSpendingKey expsk,
|
||||||
|
@ -367,8 +368,8 @@ TransactionBuilderResult TransactionBuilder::Build()
|
||||||
// Sprout JoinSplits
|
// Sprout JoinSplits
|
||||||
//
|
//
|
||||||
|
|
||||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
Ed25519SigningKey joinSplitPrivKey;
|
||||||
crypto_sign_keypair(mtx.joinSplitPubKey.begin(), joinSplitPrivKey);
|
ed25519_generate_keypair(&joinSplitPrivKey, &mtx.joinSplitPubKey);
|
||||||
|
|
||||||
// Create Sprout JSDescriptions
|
// Create Sprout JSDescriptions
|
||||||
if (!jsInputs.empty() || !jsOutputs.empty()) {
|
if (!jsInputs.empty() || !jsOutputs.empty()) {
|
||||||
|
@ -416,19 +417,19 @@ TransactionBuilderResult TransactionBuilder::Build()
|
||||||
librustzcash_sapling_proving_ctx_free(ctx);
|
librustzcash_sapling_proving_ctx_free(ctx);
|
||||||
|
|
||||||
// Create Sprout joinSplitSig
|
// Create Sprout joinSplitSig
|
||||||
if (crypto_sign_detached(
|
if (!ed25519_sign(
|
||||||
mtx.joinSplitSig.data(), NULL,
|
&joinSplitPrivKey,
|
||||||
dataToBeSigned.begin(), 32,
|
dataToBeSigned.begin(), 32,
|
||||||
joinSplitPrivKey) != 0)
|
&mtx.joinSplitSig))
|
||||||
{
|
{
|
||||||
return TransactionBuilderResult("Failed to create Sprout joinSplitSig");
|
return TransactionBuilderResult("Failed to create Sprout joinSplitSig");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check Sprout joinSplitSig
|
// Sanity check Sprout joinSplitSig
|
||||||
if (crypto_sign_verify_detached(
|
if (!ed25519_verify(
|
||||||
mtx.joinSplitSig.data(),
|
&mtx.joinSplitPubKey,
|
||||||
dataToBeSigned.begin(), 32,
|
&mtx.joinSplitSig,
|
||||||
mtx.joinSplitPubKey.begin()) != 0)
|
dataToBeSigned.begin(), 32))
|
||||||
{
|
{
|
||||||
return TransactionBuilderResult("Sprout joinSplitSig sanity check failed");
|
return TransactionBuilderResult("Sprout joinSplitSig sanity check failed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
// Sprout
|
// Sprout
|
||||||
CMutableTransaction GetValidSproutReceiveTransaction(
|
CMutableTransaction GetValidSproutReceiveTransaction(
|
||||||
const libzcash::SproutSpendingKey& sk,
|
const libzcash::SproutSpendingKey& sk,
|
||||||
|
@ -35,10 +37,8 @@ CMutableTransaction GetValidSproutReceiveTransaction(
|
||||||
mtx.vin[1].prevout.n = 0;
|
mtx.vin[1].prevout.n = 0;
|
||||||
|
|
||||||
// Generate an ephemeral keypair.
|
// Generate an ephemeral keypair.
|
||||||
uint256 joinSplitPubKey;
|
Ed25519SigningKey joinSplitPrivKey;
|
||||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
ed25519_generate_keypair(&joinSplitPrivKey, &mtx.joinSplitPubKey);
|
||||||
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
|
|
||||||
mtx.joinSplitPubKey = joinSplitPubKey;
|
|
||||||
|
|
||||||
std::array<libzcash::JSInput, 2> inputs = {
|
std::array<libzcash::JSInput, 2> inputs = {
|
||||||
libzcash::JSInput(), // dummy input
|
libzcash::JSInput(), // dummy input
|
||||||
|
@ -72,10 +72,10 @@ CMutableTransaction GetValidSproutReceiveTransaction(
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
assert(ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPrivKey,
|
||||||
joinSplitPrivKey
|
dataToBeSigned.begin(), 32,
|
||||||
) == 0);
|
&mtx.joinSplitSig));
|
||||||
|
|
||||||
return mtx;
|
return mtx;
|
||||||
}
|
}
|
||||||
|
@ -136,10 +136,8 @@ CWalletTx GetValidSproutSpend(const libzcash::SproutSpendingKey& sk,
|
||||||
mtx.vout[1].nValue = 0;
|
mtx.vout[1].nValue = 0;
|
||||||
|
|
||||||
// Generate an ephemeral keypair.
|
// Generate an ephemeral keypair.
|
||||||
uint256 joinSplitPubKey;
|
Ed25519SigningKey joinSplitPrivKey;
|
||||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
ed25519_generate_keypair(&joinSplitPrivKey, &mtx.joinSplitPubKey);
|
||||||
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
|
|
||||||
mtx.joinSplitPubKey = joinSplitPubKey;
|
|
||||||
|
|
||||||
// Fake tree for the unused witness
|
// Fake tree for the unused witness
|
||||||
SproutMerkleTree tree;
|
SproutMerkleTree tree;
|
||||||
|
@ -186,10 +184,10 @@ CWalletTx GetValidSproutSpend(const libzcash::SproutSpendingKey& sk,
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
assert(ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPrivKey,
|
||||||
joinSplitPrivKey
|
dataToBeSigned.begin(), 32,
|
||||||
) == 0);
|
&mtx.joinSplitSig));
|
||||||
CTransaction tx {mtx};
|
CTransaction tx {mtx};
|
||||||
CWalletTx wtx {NULL, tx};
|
CWalletTx wtx {NULL, tx};
|
||||||
return wtx;
|
return wtx;
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "rpc/protocol.h"
|
#include "rpc/protocol.h"
|
||||||
#include "rpc/server.h"
|
#include "rpc/server.h"
|
||||||
#include "script/interpreter.h"
|
#include "script/interpreter.h"
|
||||||
#include "sodium.h"
|
|
||||||
#include "timedata.h"
|
#include "timedata.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
|
@ -34,6 +33,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
using namespace libzcash;
|
using namespace libzcash;
|
||||||
|
|
||||||
int mta_find_output(UniValue obj, int n)
|
int mta_find_output(UniValue obj, int n)
|
||||||
|
@ -385,7 +386,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||||
|
|
||||||
// Prepare raw transaction to handle JoinSplits
|
// Prepare raw transaction to handle JoinSplits
|
||||||
CMutableTransaction mtx(tx_);
|
CMutableTransaction mtx(tx_);
|
||||||
crypto_sign_keypair(joinSplitPubKey_.begin(), joinSplitPrivKey_);
|
ed25519_generate_keypair(&joinSplitPrivKey_, &joinSplitPubKey_);
|
||||||
mtx.joinSplitPubKey = joinSplitPubKey_;
|
mtx.joinSplitPubKey = joinSplitPubKey_;
|
||||||
tx_ = CTransaction(mtx);
|
tx_ = CTransaction(mtx);
|
||||||
std::string hexMemo = std::get<1>(recipient_);
|
std::string hexMemo = std::get<1>(recipient_);
|
||||||
|
@ -823,17 +824,21 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
if (!ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPrivKey_,
|
||||||
joinSplitPrivKey_) == 0)) {
|
dataToBeSigned.begin(), 32,
|
||||||
throw std::runtime_error("crypto_sign_detached failed");
|
&mtx.joinSplitSig))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("ed25519_sign failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!(crypto_sign_verify_detached(&mtx.joinSplitSig[0],
|
if (!ed25519_verify(
|
||||||
dataToBeSigned.begin(), 32,
|
&mtx.joinSplitPubKey,
|
||||||
mtx.joinSplitPubKey.begin()) == 0)) {
|
&mtx.joinSplitSig,
|
||||||
throw std::runtime_error("crypto_sign_verify_detached failed");
|
dataToBeSigned.begin(), 32))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("ed25519_verify failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction rawTx(mtx);
|
CTransaction rawTx(mtx);
|
||||||
|
@ -875,10 +880,6 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
||||||
KeyIO keyIO(Params());
|
KeyIO keyIO(Params());
|
||||||
|
|
||||||
// !!! Payment disclosure START
|
// !!! Payment disclosure START
|
||||||
unsigned char buffer[32] = {0};
|
|
||||||
memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer
|
|
||||||
std::vector<unsigned char> vch(&buffer[0], &buffer[0] + 32);
|
|
||||||
uint256 joinSplitPrivKey = uint256(vch);
|
|
||||||
size_t js_index = tx_.vJoinSplit.size() - 1;
|
size_t js_index = tx_.vJoinSplit.size() - 1;
|
||||||
uint256 placeholder;
|
uint256 placeholder;
|
||||||
for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||||
|
@ -887,7 +888,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
||||||
PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index};
|
PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index};
|
||||||
JSOutput output = outputs[mapped_index];
|
JSOutput output = outputs[mapped_index];
|
||||||
libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output
|
libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output
|
||||||
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
|
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey_, zaddr};
|
||||||
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
|
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
|
||||||
|
|
||||||
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), keyIO.EncodePaymentAddress(zaddr));
|
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), keyIO.EncodePaymentAddress(zaddr));
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
// Default transaction fee if caller does not specify one.
|
// Default transaction fee if caller does not specify one.
|
||||||
#define MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE 10000
|
#define MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE 10000
|
||||||
|
|
||||||
|
@ -95,8 +97,8 @@ private:
|
||||||
CTxDestination toTaddr_;
|
CTxDestination toTaddr_;
|
||||||
PaymentAddress toPaymentAddress_;
|
PaymentAddress toPaymentAddress_;
|
||||||
|
|
||||||
uint256 joinSplitPubKey_;
|
Ed25519VerificationKey joinSplitPubKey_;
|
||||||
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
|
Ed25519SigningKey joinSplitPrivKey_;
|
||||||
|
|
||||||
// The key is the result string from calling JSOutPoint::ToString()
|
// The key is the result string from calling JSOutPoint::ToString()
|
||||||
std::unordered_map<std::string, MergeToAddressWitnessAnchorData> jsopWitnessAnchorMap;
|
std::unordered_map<std::string, MergeToAddressWitnessAnchorData> jsopWitnessAnchorMap;
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "script/interpreter.h"
|
#include "script/interpreter.h"
|
||||||
#include "utiltime.h"
|
#include "utiltime.h"
|
||||||
#include "zcash/IncrementalMerkleTree.hpp"
|
#include "zcash/IncrementalMerkleTree.hpp"
|
||||||
#include "sodium.h"
|
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
#include "wallet/paymentdisclosuredb.h"
|
#include "wallet/paymentdisclosuredb.h"
|
||||||
|
|
||||||
|
@ -36,6 +35,8 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
using namespace libzcash;
|
using namespace libzcash;
|
||||||
|
|
||||||
int find_output(UniValue obj, int n) {
|
int find_output(UniValue obj, int n) {
|
||||||
|
@ -508,7 +509,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||||
|
|
||||||
// Prepare raw transaction to handle JoinSplits
|
// Prepare raw transaction to handle JoinSplits
|
||||||
CMutableTransaction mtx(tx_);
|
CMutableTransaction mtx(tx_);
|
||||||
crypto_sign_keypair(joinSplitPubKey_.begin(), joinSplitPrivKey_);
|
ed25519_generate_keypair(&joinSplitPrivKey_, &joinSplitPubKey_);
|
||||||
mtx.joinSplitPubKey = joinSplitPubKey_;
|
mtx.joinSplitPubKey = joinSplitPubKey_;
|
||||||
tx_ = CTransaction(mtx);
|
tx_ = CTransaction(mtx);
|
||||||
|
|
||||||
|
@ -1100,21 +1101,21 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
if (!ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPrivKey_,
|
||||||
joinSplitPrivKey_
|
dataToBeSigned.begin(), 32,
|
||||||
) == 0))
|
&mtx.joinSplitSig))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("crypto_sign_detached failed");
|
throw std::runtime_error("ed25519_sign failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!(crypto_sign_verify_detached(&mtx.joinSplitSig[0],
|
if (!ed25519_verify(
|
||||||
dataToBeSigned.begin(), 32,
|
&mtx.joinSplitPubKey,
|
||||||
mtx.joinSplitPubKey.begin()
|
&mtx.joinSplitSig,
|
||||||
) == 0))
|
dataToBeSigned.begin(), 32))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("crypto_sign_verify_detached failed");
|
throw std::runtime_error("ed25519_verify failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction rawTx(mtx);
|
CTransaction rawTx(mtx);
|
||||||
|
@ -1156,10 +1157,6 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||||
KeyIO keyIO(Params());
|
KeyIO keyIO(Params());
|
||||||
|
|
||||||
// !!! Payment disclosure START
|
// !!! Payment disclosure START
|
||||||
unsigned char buffer[32] = {0};
|
|
||||||
memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer
|
|
||||||
std::vector<unsigned char> vch(&buffer[0], &buffer[0] + 32);
|
|
||||||
uint256 joinSplitPrivKey = uint256(vch);
|
|
||||||
size_t js_index = tx_.vJoinSplit.size() - 1;
|
size_t js_index = tx_.vJoinSplit.size() - 1;
|
||||||
uint256 placeholder;
|
uint256 placeholder;
|
||||||
for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||||
|
@ -1168,7 +1165,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||||
PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index};
|
PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index};
|
||||||
JSOutput output = outputs[mapped_index];
|
JSOutput output = outputs[mapped_index];
|
||||||
libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output
|
libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output
|
||||||
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
|
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey_, zaddr};
|
||||||
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
|
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
|
||||||
|
|
||||||
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), keyIO.EncodePaymentAddress(zaddr));
|
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), keyIO.EncodePaymentAddress(zaddr));
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
// Default transaction fee if caller does not specify one.
|
// Default transaction fee if caller does not specify one.
|
||||||
#define ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE 10000
|
#define ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE 10000
|
||||||
|
|
||||||
|
@ -114,9 +116,9 @@ private:
|
||||||
CTxDestination fromtaddr_;
|
CTxDestination fromtaddr_;
|
||||||
PaymentAddress frompaymentaddress_;
|
PaymentAddress frompaymentaddress_;
|
||||||
SpendingKey spendingkey_;
|
SpendingKey spendingkey_;
|
||||||
|
|
||||||
uint256 joinSplitPubKey_;
|
Ed25519VerificationKey joinSplitPubKey_;
|
||||||
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
|
Ed25519SigningKey joinSplitPrivKey_;
|
||||||
|
|
||||||
// The key is the result string from calling JSOutPoint::ToString()
|
// The key is the result string from calling JSOutPoint::ToString()
|
||||||
std::unordered_map<std::string, WitnessAnchorData> jsopWitnessAnchorMap;
|
std::unordered_map<std::string, WitnessAnchorData> jsopWitnessAnchorMap;
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "script/interpreter.h"
|
#include "script/interpreter.h"
|
||||||
#include "utiltime.h"
|
#include "utiltime.h"
|
||||||
#include "zcash/IncrementalMerkleTree.hpp"
|
#include "zcash/IncrementalMerkleTree.hpp"
|
||||||
#include "sodium.h"
|
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
#include "wallet/paymentdisclosuredb.h"
|
#include "wallet/paymentdisclosuredb.h"
|
||||||
|
|
||||||
|
@ -36,6 +35,8 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
using namespace libzcash;
|
using namespace libzcash;
|
||||||
|
|
||||||
static int find_output(UniValue obj, int n) {
|
static int find_output(UniValue obj, int n) {
|
||||||
|
@ -209,7 +210,7 @@ bool ShieldToAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) co
|
||||||
|
|
||||||
// Prepare raw transaction to handle JoinSplits
|
// Prepare raw transaction to handle JoinSplits
|
||||||
CMutableTransaction mtx(m_op->tx_);
|
CMutableTransaction mtx(m_op->tx_);
|
||||||
crypto_sign_keypair(m_op->joinSplitPubKey_.begin(), m_op->joinSplitPrivKey_);
|
ed25519_generate_keypair(&m_op->joinSplitPrivKey_, &m_op->joinSplitPubKey_);
|
||||||
mtx.joinSplitPubKey = m_op->joinSplitPubKey_;
|
mtx.joinSplitPubKey = m_op->joinSplitPubKey_;
|
||||||
m_op->tx_ = CTransaction(mtx);
|
m_op->tx_ = CTransaction(mtx);
|
||||||
|
|
||||||
|
@ -334,21 +335,21 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
if (!ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPrivKey_,
|
||||||
joinSplitPrivKey_
|
dataToBeSigned.begin(), 32,
|
||||||
) == 0))
|
&mtx.joinSplitSig))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("crypto_sign_detached failed");
|
throw std::runtime_error("ed25519_sign failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!(crypto_sign_verify_detached(&mtx.joinSplitSig[0],
|
if (!ed25519_verify(
|
||||||
dataToBeSigned.begin(), 32,
|
&mtx.joinSplitPubKey,
|
||||||
mtx.joinSplitPubKey.begin()
|
&mtx.joinSplitSig,
|
||||||
) == 0))
|
dataToBeSigned.begin(), 32))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("crypto_sign_verify_detached failed");
|
throw std::runtime_error("ed25519_verify failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction rawTx(mtx);
|
CTransaction rawTx(mtx);
|
||||||
|
@ -390,10 +391,6 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
|
||||||
KeyIO keyIO(Params());
|
KeyIO keyIO(Params());
|
||||||
|
|
||||||
// !!! Payment disclosure START
|
// !!! Payment disclosure START
|
||||||
unsigned char buffer[32] = {0};
|
|
||||||
memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer
|
|
||||||
std::vector<unsigned char> vch(&buffer[0], &buffer[0] + 32);
|
|
||||||
uint256 joinSplitPrivKey = uint256(vch);
|
|
||||||
size_t js_index = tx_.vJoinSplit.size() - 1;
|
size_t js_index = tx_.vJoinSplit.size() - 1;
|
||||||
uint256 placeholder;
|
uint256 placeholder;
|
||||||
for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||||
|
@ -402,7 +399,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
|
||||||
PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index};
|
PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index};
|
||||||
JSOutput output = outputs[mapped_index];
|
JSOutput output = outputs[mapped_index];
|
||||||
libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output
|
libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output
|
||||||
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
|
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey_, zaddr};
|
||||||
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
|
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
|
||||||
|
|
||||||
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), keyIO.EncodePaymentAddress(zaddr));
|
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), keyIO.EncodePaymentAddress(zaddr));
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
// Default transaction fee if caller does not specify one.
|
// Default transaction fee if caller does not specify one.
|
||||||
#define SHIELD_COINBASE_DEFAULT_MINERS_FEE 10000
|
#define SHIELD_COINBASE_DEFAULT_MINERS_FEE 10000
|
||||||
|
|
||||||
|
@ -74,8 +76,8 @@ private:
|
||||||
CAmount fee_;
|
CAmount fee_;
|
||||||
PaymentAddress tozaddr_;
|
PaymentAddress tozaddr_;
|
||||||
|
|
||||||
uint256 joinSplitPubKey_;
|
Ed25519VerificationKey joinSplitPubKey_;
|
||||||
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
|
Ed25519SigningKey joinSplitPrivKey_;
|
||||||
|
|
||||||
std::vector<ShieldCoinbaseUTXO> inputs_;
|
std::vector<ShieldCoinbaseUTXO> inputs_;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "random.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
#include "utilstrencodings.h"
|
#include "utilstrencodings.h"
|
||||||
|
@ -20,12 +21,12 @@
|
||||||
#include "wallet/paymentdisclosure.h"
|
#include "wallet/paymentdisclosure.h"
|
||||||
#include "wallet/paymentdisclosuredb.h"
|
#include "wallet/paymentdisclosuredb.h"
|
||||||
|
|
||||||
#include "sodium.h"
|
|
||||||
|
|
||||||
#include <boost/uuid/uuid.hpp>
|
#include <boost/uuid/uuid.hpp>
|
||||||
#include <boost/uuid/uuid_generators.hpp>
|
#include <boost/uuid/uuid_generators.hpp>
|
||||||
#include <boost/uuid/uuid_io.hpp>
|
#include <boost/uuid/uuid_io.hpp>
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -43,13 +44,6 @@ using namespace std;
|
||||||
|
|
||||||
static boost::uuids::random_generator uuidgen;
|
static boost::uuids::random_generator uuidgen;
|
||||||
|
|
||||||
static uint256 random_uint256()
|
|
||||||
{
|
|
||||||
uint256 ret;
|
|
||||||
randombytes_buf(ret.begin(), 32);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subclass of PaymentDisclosureDB to add debugging methods
|
// Subclass of PaymentDisclosureDB to add debugging methods
|
||||||
class PaymentDisclosureDBTest : public PaymentDisclosureDB {
|
class PaymentDisclosureDBTest : public PaymentDisclosureDB {
|
||||||
public:
|
public:
|
||||||
|
@ -103,21 +97,16 @@ TEST(paymentdisclosure, mainnet) {
|
||||||
|
|
||||||
for (int i=0; i<NUM_TRIES; i++) {
|
for (int i=0; i<NUM_TRIES; i++) {
|
||||||
// Generate an ephemeral keypair for joinsplit sig.
|
// Generate an ephemeral keypair for joinsplit sig.
|
||||||
uint256 joinSplitPubKey;
|
Ed25519SigningKey joinSplitPrivKey;
|
||||||
unsigned char buffer[crypto_sign_SECRETKEYBYTES] = {0};
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
crypto_sign_keypair(joinSplitPubKey.begin(), &buffer[0]);
|
ed25519_generate_keypair(&joinSplitPrivKey, &joinSplitPubKey);
|
||||||
|
|
||||||
// First 32 bytes contain private key, second 32 bytes contain public key.
|
|
||||||
ASSERT_EQ(0, memcmp(joinSplitPubKey.begin(), &buffer[0]+32, 32));
|
|
||||||
std::vector<unsigned char> vch(&buffer[0], &buffer[0] + 32);
|
|
||||||
uint256 joinSplitPrivKey = uint256(vch);
|
|
||||||
|
|
||||||
// Create payment disclosure key and info data to store in test database
|
// Create payment disclosure key and info data to store in test database
|
||||||
size_t js = random_uint256().GetCheapHash() % std::numeric_limits<size_t>::max();
|
size_t js = GetRandHash().GetCheapHash() % std::numeric_limits<size_t>::max();
|
||||||
uint8_t n = random_uint256().GetCheapHash() % std::numeric_limits<uint8_t>::max();
|
uint8_t n = GetRandHash().GetCheapHash() % std::numeric_limits<uint8_t>::max();
|
||||||
PaymentDisclosureKey key { random_uint256(), js, n};
|
PaymentDisclosureKey key { GetRandHash(), js, n};
|
||||||
PaymentDisclosureInfo info;
|
PaymentDisclosureInfo info;
|
||||||
info.esk = random_uint256();
|
info.esk = GetRandHash();
|
||||||
info.joinSplitPrivKey = joinSplitPrivKey;
|
info.joinSplitPrivKey = joinSplitPrivKey;
|
||||||
info.zaddr = libzcash::SproutSpendingKey::random().address();
|
info.zaddr = libzcash::SproutSpendingKey::random().address();
|
||||||
ASSERT_TRUE(mydb.Put(key, info));
|
ASSERT_TRUE(mydb.Put(key, info));
|
||||||
|
@ -128,8 +117,8 @@ TEST(paymentdisclosure, mainnet) {
|
||||||
ASSERT_EQ(info, info2);
|
ASSERT_EQ(info, info2);
|
||||||
|
|
||||||
// Modify this local variable and confirm it no longer matches
|
// Modify this local variable and confirm it no longer matches
|
||||||
info2.esk = random_uint256();
|
info2.esk = GetRandHash();
|
||||||
info2.joinSplitPrivKey = random_uint256();
|
GetRandBytes(info2.joinSplitPrivKey.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||||
info2.zaddr = libzcash::SproutSpendingKey::random().address();
|
info2.zaddr = libzcash::SproutSpendingKey::random().address();
|
||||||
ASSERT_NE(info, info2);
|
ASSERT_NE(info, info2);
|
||||||
|
|
||||||
|
@ -147,33 +136,29 @@ TEST(paymentdisclosure, mainnet) {
|
||||||
uint256 dataToBeSigned = SerializeHash(payload, SER_GETHASH, 0);
|
uint256 dataToBeSigned = SerializeHash(payload, SER_GETHASH, 0);
|
||||||
|
|
||||||
// Compute the payload signature
|
// Compute the payload signature
|
||||||
unsigned char payloadSig[64];
|
Ed25519Signature payloadSig;
|
||||||
if (!(crypto_sign_detached(&payloadSig[0], NULL,
|
if (!ed25519_sign(
|
||||||
|
&joinSplitPrivKey,
|
||||||
dataToBeSigned.begin(), 32,
|
dataToBeSigned.begin(), 32,
|
||||||
&buffer[0] // buffer containing both private and public key required
|
&payloadSig))
|
||||||
) == 0))
|
|
||||||
{
|
{
|
||||||
throw std::runtime_error("crypto_sign_detached failed");
|
throw std::runtime_error("ed25519_sign failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!(crypto_sign_verify_detached(&payloadSig[0],
|
if (!ed25519_verify(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPubKey,
|
||||||
joinSplitPubKey.begin()
|
&payloadSig,
|
||||||
) == 0))
|
dataToBeSigned.begin(), 32))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("crypto_sign_verify_detached failed");
|
throw std::runtime_error("ed25519_verify failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert signature buffer to boost array
|
|
||||||
std::array<unsigned char, 64> arrayPayloadSig;
|
|
||||||
memcpy(arrayPayloadSig.data(), &payloadSig[0], 64);
|
|
||||||
|
|
||||||
// Payment disclosure blob to pass around
|
// Payment disclosure blob to pass around
|
||||||
PaymentDisclosure pd = {payload, arrayPayloadSig};
|
PaymentDisclosure pd = {payload, payloadSig};
|
||||||
|
|
||||||
// Test payment disclosure constructors
|
// Test payment disclosure constructors
|
||||||
PaymentDisclosure pd2(payload, arrayPayloadSig);
|
PaymentDisclosure pd2(payload, payloadSig);
|
||||||
ASSERT_EQ(pd, pd2);
|
ASSERT_EQ(pd, pd2);
|
||||||
PaymentDisclosure pd3(joinSplitPubKey, key, info, payload.message);
|
PaymentDisclosure pd3(joinSplitPubKey, key, info, payload.message);
|
||||||
ASSERT_EQ(pd, pd3);
|
ASSERT_EQ(pd, pd3);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "key_io.h"
|
#include "key_io.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
std::string PaymentDisclosureInfo::ToString() const {
|
std::string PaymentDisclosureInfo::ToString() const {
|
||||||
KeyIO keyIO(Params());
|
KeyIO keyIO(Params());
|
||||||
return strprintf("PaymentDisclosureInfo(version=%d, esk=%s, joinSplitPrivKey=<omitted>, address=%s)",
|
return strprintf("PaymentDisclosureInfo(version=%d, esk=%s, joinSplitPrivKey=<omitted>, address=%s)",
|
||||||
|
@ -14,7 +16,7 @@ std::string PaymentDisclosureInfo::ToString() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PaymentDisclosure::ToString() const {
|
std::string PaymentDisclosure::ToString() const {
|
||||||
std::string s = HexStr(payloadSig.begin(), payloadSig.end());
|
std::string s = HexStr(payloadSig.bytes, payloadSig.bytes + ED25519_SIGNATURE_LEN);
|
||||||
return strprintf("PaymentDisclosure(payload=%s, payloadSig=%s)", payload.ToString(), s);
|
return strprintf("PaymentDisclosure(payload=%s, payloadSig=%s)", payload.ToString(), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +26,11 @@ std::string PaymentDisclosurePayload::ToString() const {
|
||||||
version, esk.ToString(), txid.ToString(), js, n, keyIO.EncodePaymentAddress(zaddr), message);
|
version, esk.ToString(), txid.ToString(), js, n, keyIO.EncodePaymentAddress(zaddr), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
PaymentDisclosure::PaymentDisclosure(const uint256 &joinSplitPubKey, const PaymentDisclosureKey &key, const PaymentDisclosureInfo &info, const std::string &message)
|
PaymentDisclosure::PaymentDisclosure(
|
||||||
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
|
const PaymentDisclosureKey& key,
|
||||||
|
const PaymentDisclosureInfo& info,
|
||||||
|
const std::string& message)
|
||||||
{
|
{
|
||||||
// Populate payload member variable
|
// Populate payload member variable
|
||||||
payload.version = info.version; // experimental = 0, production = 1 etc.
|
payload.version = info.version; // experimental = 0, production = 1 etc.
|
||||||
|
@ -40,28 +46,24 @@ PaymentDisclosure::PaymentDisclosure(const uint256 &joinSplitPubKey, const Payme
|
||||||
|
|
||||||
LogPrint("paymentdisclosure", "Payment Disclosure: signing raw payload = %s\n", dataToBeSigned.ToString());
|
LogPrint("paymentdisclosure", "Payment Disclosure: signing raw payload = %s\n", dataToBeSigned.ToString());
|
||||||
|
|
||||||
// Prepare buffer to store ed25519 key pair in libsodium-compatible format
|
|
||||||
unsigned char bufferKeyPair[64];
|
|
||||||
memcpy(&bufferKeyPair[0], info.joinSplitPrivKey.begin(), 32);
|
|
||||||
memcpy(&bufferKeyPair[32], joinSplitPubKey.begin(), 32);
|
|
||||||
|
|
||||||
// Compute payload signature member variable
|
// Compute payload signature member variable
|
||||||
if (!(crypto_sign_detached(payloadSig.data(), NULL,
|
if (!ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&info.joinSplitPrivKey,
|
||||||
&bufferKeyPair[0]
|
dataToBeSigned.begin(), 32,
|
||||||
) == 0))
|
&payloadSig))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("crypto_sign_detached failed");
|
throw std::runtime_error("ed25519_sign failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!(crypto_sign_verify_detached(payloadSig.data(),
|
if (!ed25519_verify(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPubKey,
|
||||||
joinSplitPubKey.begin()) == 0))
|
&payloadSig,
|
||||||
|
dataToBeSigned.begin(), 32))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("crypto_sign_verify_detached failed");
|
throw std::runtime_error("ed25519_verify failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sigString = HexStr(payloadSig.data(), payloadSig.data() + payloadSig.size());
|
std::string sigString = HexStr(payloadSig.bytes, payloadSig.bytes + ED25519_SIGNATURE_LEN);
|
||||||
LogPrint("paymentdisclosure", "Payment Disclosure: signature = %s\n", sigString);
|
LogPrint("paymentdisclosure", "Payment Disclosure: signature = %s\n", sigString);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
|
|
||||||
// Ensure that the two different protocol messages, payment disclosure blobs and transactions,
|
// Ensure that the two different protocol messages, payment disclosure blobs and transactions,
|
||||||
// which are signed with the same key, joinSplitPrivKey, have disjoint encodings such that an
|
// which are signed with the same key, joinSplitPrivKey, have disjoint encodings such that an
|
||||||
|
@ -36,7 +38,7 @@ typedef JSOutPoint PaymentDisclosureKey;
|
||||||
struct PaymentDisclosureInfo {
|
struct PaymentDisclosureInfo {
|
||||||
uint8_t version; // 0 = experimental, 1 = first production version, etc.
|
uint8_t version; // 0 = experimental, 1 = first production version, etc.
|
||||||
uint256 esk; // zcash/NoteEncryption.cpp
|
uint256 esk; // zcash/NoteEncryption.cpp
|
||||||
uint256 joinSplitPrivKey; // primitives/transaction.h
|
Ed25519SigningKey joinSplitPrivKey; // primitives/transaction.h
|
||||||
// ed25519 - not tied to implementation e.g. libsodium, see ed25519 rfc
|
// ed25519 - not tied to implementation e.g. libsodium, see ed25519 rfc
|
||||||
|
|
||||||
libzcash::SproutPaymentAddress zaddr;
|
libzcash::SproutPaymentAddress zaddr;
|
||||||
|
@ -44,7 +46,7 @@ struct PaymentDisclosureInfo {
|
||||||
PaymentDisclosureInfo() : version(PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL) {
|
PaymentDisclosureInfo() : version(PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PaymentDisclosureInfo(uint8_t v, uint256 esk, uint256 key, libzcash::SproutPaymentAddress zaddr) : version(v), esk(esk), joinSplitPrivKey(key), zaddr(zaddr) { }
|
PaymentDisclosureInfo(uint8_t v, uint256 esk, Ed25519SigningKey key, libzcash::SproutPaymentAddress zaddr) : version(v), esk(esk), joinSplitPrivKey(key), zaddr(zaddr) { }
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
@ -59,7 +61,14 @@ struct PaymentDisclosureInfo {
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
friend bool operator==(const PaymentDisclosureInfo& a, const PaymentDisclosureInfo& b) {
|
friend bool operator==(const PaymentDisclosureInfo& a, const PaymentDisclosureInfo& b) {
|
||||||
return (a.version == b.version && a.esk == b.esk && a.joinSplitPrivKey == b.joinSplitPrivKey && a.zaddr == b.zaddr);
|
return (
|
||||||
|
a.version == b.version &&
|
||||||
|
a.esk == b.esk &&
|
||||||
|
std::equal(
|
||||||
|
a.joinSplitPrivKey.bytes,
|
||||||
|
a.joinSplitPrivKey.bytes + ED25519_SIGNING_KEY_LEN,
|
||||||
|
b.joinSplitPrivKey.bytes) &&
|
||||||
|
a.zaddr == b.zaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const PaymentDisclosureInfo& a, const PaymentDisclosureInfo& b) {
|
friend bool operator!=(const PaymentDisclosureInfo& a, const PaymentDisclosureInfo& b) {
|
||||||
|
@ -114,12 +123,16 @@ struct PaymentDisclosurePayload {
|
||||||
|
|
||||||
struct PaymentDisclosure {
|
struct PaymentDisclosure {
|
||||||
PaymentDisclosurePayload payload;
|
PaymentDisclosurePayload payload;
|
||||||
std::array<unsigned char, 64> payloadSig;
|
Ed25519Signature payloadSig;
|
||||||
// We use boost array because serialize doesn't like char buffer, otherwise we could do: unsigned char payloadSig[64];
|
// We use boost array because serialize doesn't like char buffer, otherwise we could do: unsigned char payloadSig[64];
|
||||||
|
|
||||||
PaymentDisclosure() {};
|
PaymentDisclosure() {};
|
||||||
PaymentDisclosure(const PaymentDisclosurePayload payload, const std::array<unsigned char, 64> sig) : payload(payload), payloadSig(sig) {};
|
PaymentDisclosure(const PaymentDisclosurePayload payload, const Ed25519Signature sig) : payload(payload), payloadSig(sig) {};
|
||||||
PaymentDisclosure(const uint256& joinSplitPubKey, const PaymentDisclosureKey& key, const PaymentDisclosureInfo& info, const std::string& message);
|
PaymentDisclosure(
|
||||||
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
|
const PaymentDisclosureKey& key,
|
||||||
|
const PaymentDisclosureInfo& info,
|
||||||
|
const std::string& message);
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
@ -132,7 +145,13 @@ struct PaymentDisclosure {
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
friend bool operator==(const PaymentDisclosure& a, const PaymentDisclosure& b) {
|
friend bool operator==(const PaymentDisclosure& a, const PaymentDisclosure& b) {
|
||||||
return (a.payload == b.payload && a.payloadSig == b.payloadSig);
|
return (
|
||||||
|
a.payload == b.payload &&
|
||||||
|
std::equal(
|
||||||
|
a.payloadSig.bytes,
|
||||||
|
a.payloadSig.bytes + ED25519_SIGNATURE_LEN,
|
||||||
|
b.payloadSig.bytes)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const PaymentDisclosure& a, const PaymentDisclosure& b) {
|
friend bool operator!=(const PaymentDisclosure& a, const PaymentDisclosure& b) {
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include "zcash/Note.hpp"
|
#include "zcash/Note.hpp"
|
||||||
#include "zcash/NoteEncryption.hpp"
|
#include "zcash/NoteEncryption.hpp"
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace libzcash;
|
using namespace libzcash;
|
||||||
|
|
||||||
|
@ -238,13 +240,22 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
|
||||||
o.pushKV("version", pd.payload.version);
|
o.pushKV("version", pd.payload.version);
|
||||||
o.pushKV("onetimePrivKey", pd.payload.esk.ToString());
|
o.pushKV("onetimePrivKey", pd.payload.esk.ToString());
|
||||||
o.pushKV("message", pd.payload.message);
|
o.pushKV("message", pd.payload.message);
|
||||||
o.pushKV("joinSplitPubKey", tx.joinSplitPubKey.ToString());
|
|
||||||
|
// Copy joinSplitPubKey into a uint256 so that
|
||||||
|
// it is byte-flipped in the RPC output.
|
||||||
|
uint256 joinSplitPubKey;
|
||||||
|
std::copy(
|
||||||
|
tx.joinSplitPubKey.bytes,
|
||||||
|
tx.joinSplitPubKey.bytes + ED25519_VERIFICATION_KEY_LEN,
|
||||||
|
joinSplitPubKey.begin());
|
||||||
|
o.pushKV("joinSplitPubKey", joinSplitPubKey.ToString());
|
||||||
|
|
||||||
// Verify the payment disclosure was signed using the same key as the transaction i.e. the joinSplitPrivKey.
|
// Verify the payment disclosure was signed using the same key as the transaction i.e. the joinSplitPrivKey.
|
||||||
uint256 dataToBeSigned = SerializeHash(pd.payload, SER_GETHASH, 0);
|
uint256 dataToBeSigned = SerializeHash(pd.payload, SER_GETHASH, 0);
|
||||||
bool sigVerified = (crypto_sign_verify_detached(pd.payloadSig.data(),
|
bool sigVerified = ed25519_verify(
|
||||||
dataToBeSigned.begin(), 32,
|
&tx.joinSplitPubKey,
|
||||||
tx.joinSplitPubKey.begin()) == 0);
|
&pd.payloadSig,
|
||||||
|
dataToBeSigned.begin(), 32);
|
||||||
o.pushKV("signatureVerified", sigVerified);
|
o.pushKV("signatureVerified", sigVerified);
|
||||||
if (!sigVerified) {
|
if (!sigVerified) {
|
||||||
errs.push_back("Payment disclosure signature does not match transaction signature");
|
errs.push_back("Payment disclosure signature does not match transaction signature");
|
||||||
|
|
|
@ -34,8 +34,6 @@
|
||||||
#include "wallet/asyncrpcoperation_sendmany.h"
|
#include "wallet/asyncrpcoperation_sendmany.h"
|
||||||
#include "wallet/asyncrpcoperation_shieldcoinbase.h"
|
#include "wallet/asyncrpcoperation_shieldcoinbase.h"
|
||||||
|
|
||||||
#include "sodium.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
|
@ -45,6 +43,8 @@
|
||||||
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
|
#include <rust/ed25519.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
using namespace libzcash;
|
using namespace libzcash;
|
||||||
|
@ -2760,7 +2760,7 @@ UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp)
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
uint256 joinSplitPubKey;
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
uint256 anchor = SproutMerkleTree().root();
|
uint256 anchor = SproutMerkleTree().root();
|
||||||
JSDescription samplejoinsplit(joinSplitPubKey,
|
JSDescription samplejoinsplit(joinSplitPubKey,
|
||||||
anchor,
|
anchor,
|
||||||
|
@ -3128,9 +3128,9 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
|
||||||
throw runtime_error("unsupported joinsplit input/output counts");
|
throw runtime_error("unsupported joinsplit input/output counts");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 joinSplitPubKey;
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
Ed25519SigningKey joinSplitPrivKey;
|
||||||
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
|
ed25519_generate_keypair(&joinSplitPrivKey, &joinSplitPubKey);
|
||||||
|
|
||||||
CMutableTransaction mtx(tx);
|
CMutableTransaction mtx(tx);
|
||||||
mtx.nVersion = 4;
|
mtx.nVersion = 4;
|
||||||
|
@ -3158,16 +3158,16 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
assert(ed25519_sign(
|
||||||
dataToBeSigned.begin(), 32,
|
&joinSplitPrivKey,
|
||||||
joinSplitPrivKey
|
dataToBeSigned.begin(), 32,
|
||||||
) == 0);
|
&mtx.joinSplitSig));
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
assert(crypto_sign_verify_detached(&mtx.joinSplitSig[0],
|
assert(ed25519_verify(
|
||||||
dataToBeSigned.begin(), 32,
|
&mtx.joinSplitPubKey,
|
||||||
mtx.joinSplitPubKey.begin()
|
&mtx.joinSplitSig,
|
||||||
) == 0);
|
dataToBeSigned.begin(), 32));
|
||||||
|
|
||||||
CTransaction rawTx(mtx);
|
CTransaction rawTx(mtx);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace libzcash {
|
||||||
std::array<SproutNote, NumOutputs>& out_notes,
|
std::array<SproutNote, NumOutputs>& out_notes,
|
||||||
std::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
std::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
||||||
uint256& out_ephemeralKey,
|
uint256& out_ephemeralKey,
|
||||||
const uint256& joinSplitPubKey,
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
uint256& out_randomSeed,
|
uint256& out_randomSeed,
|
||||||
std::array<uint256, NumInputs>& out_macs,
|
std::array<uint256, NumInputs>& out_macs,
|
||||||
std::array<uint256, NumInputs>& out_nullifiers,
|
std::array<uint256, NumInputs>& out_nullifiers,
|
||||||
|
@ -205,7 +205,7 @@ template<size_t NumInputs, size_t NumOutputs>
|
||||||
uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
|
uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
|
||||||
const uint256& randomSeed,
|
const uint256& randomSeed,
|
||||||
const std::array<uint256, NumInputs>& nullifiers,
|
const std::array<uint256, NumInputs>& nullifiers,
|
||||||
const uint256& joinSplitPubKey
|
const Ed25519VerificationKey& joinSplitPubKey
|
||||||
) {
|
) {
|
||||||
const unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES]
|
const unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES]
|
||||||
= {'Z','c','a','s','h','C','o','m','p','u','t','e','h','S','i','g'};
|
= {'Z','c','a','s','h','C','o','m','p','u','t','e','h','S','i','g'};
|
||||||
|
@ -216,7 +216,7 @@ uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
|
||||||
block.insert(block.end(), nullifiers[i].begin(), nullifiers[i].end());
|
block.insert(block.end(), nullifiers[i].begin(), nullifiers[i].end());
|
||||||
}
|
}
|
||||||
|
|
||||||
block.insert(block.end(), joinSplitPubKey.begin(), joinSplitPubKey.end());
|
block.insert(block.end(), joinSplitPubKey.bytes, joinSplitPubKey.bytes + ED25519_VERIFICATION_KEY_LEN);
|
||||||
|
|
||||||
uint256 output;
|
uint256 output;
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
namespace libzcash {
|
namespace libzcash {
|
||||||
|
|
||||||
class JSInput {
|
class JSInput {
|
||||||
|
@ -48,7 +50,7 @@ class JoinSplit {
|
||||||
public:
|
public:
|
||||||
static uint256 h_sig(const uint256& randomSeed,
|
static uint256 h_sig(const uint256& randomSeed,
|
||||||
const std::array<uint256, NumInputs>& nullifiers,
|
const std::array<uint256, NumInputs>& nullifiers,
|
||||||
const uint256& joinSplitPubKey
|
const Ed25519VerificationKey& joinSplitPubKey
|
||||||
);
|
);
|
||||||
|
|
||||||
// Compute nullifiers, macs, note commitments & encryptions, and SNARK proof
|
// Compute nullifiers, macs, note commitments & encryptions, and SNARK proof
|
||||||
|
@ -58,7 +60,7 @@ public:
|
||||||
std::array<SproutNote, NumOutputs>& out_notes,
|
std::array<SproutNote, NumOutputs>& out_notes,
|
||||||
std::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
std::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
||||||
uint256& out_ephemeralKey,
|
uint256& out_ephemeralKey,
|
||||||
const uint256& joinSplitPubKey,
|
const Ed25519VerificationKey& joinSplitPubKey,
|
||||||
uint256& out_randomSeed,
|
uint256& out_randomSeed,
|
||||||
std::array<uint256, NumInputs>& out_hmacs,
|
std::array<uint256, NumInputs>& out_hmacs,
|
||||||
std::array<uint256, NumInputs>& out_nullifiers,
|
std::array<uint256, NumInputs>& out_nullifiers,
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#include "NoteEncryption.hpp"
|
#include "NoteEncryption.hpp"
|
||||||
|
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "sodium.h"
|
#include "sodium.h"
|
||||||
#include <boost/static_assert.hpp>
|
#include <boost/static_assert.hpp>
|
||||||
|
@ -444,10 +447,7 @@ uint256 NoteEncryption<MLEN>::generate_pubkey(const uint256 &sk_enc)
|
||||||
|
|
||||||
uint256 random_uint256()
|
uint256 random_uint256()
|
||||||
{
|
{
|
||||||
uint256 ret;
|
return GetRandHash();
|
||||||
randombytes_buf(ret.begin(), 32);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint252 random_uint252()
|
uint252 random_uint252()
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "policy/policy.h"
|
#include "policy/policy.h"
|
||||||
#include "pow.h"
|
#include "pow.h"
|
||||||
#include "proof_verifier.h"
|
#include "proof_verifier.h"
|
||||||
|
#include "random.h"
|
||||||
#include "rpc/server.h"
|
#include "rpc/server.h"
|
||||||
#include "script/sign.h"
|
#include "script/sign.h"
|
||||||
#include "sodium.h"
|
#include "sodium.h"
|
||||||
|
@ -35,6 +36,8 @@
|
||||||
#include "zcash/Note.hpp"
|
#include "zcash/Note.hpp"
|
||||||
#include "librustzcash.h"
|
#include "librustzcash.h"
|
||||||
|
|
||||||
|
#include <rust/ed25519/types.h>
|
||||||
|
|
||||||
using namespace libzcash;
|
using namespace libzcash;
|
||||||
// This method is based on Shutdown from init.cpp
|
// This method is based on Shutdown from init.cpp
|
||||||
void pre_wallet_load()
|
void pre_wallet_load()
|
||||||
|
@ -95,7 +98,7 @@ double benchmark_sleep()
|
||||||
|
|
||||||
double benchmark_create_joinsplit()
|
double benchmark_create_joinsplit()
|
||||||
{
|
{
|
||||||
uint256 joinSplitPubKey;
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
|
|
||||||
/* Get the anchor of an empty commitment tree. */
|
/* Get the anchor of an empty commitment tree. */
|
||||||
uint256 anchor = SproutMerkleTree().root();
|
uint256 anchor = SproutMerkleTree().root();
|
||||||
|
@ -140,7 +143,7 @@ double benchmark_verify_joinsplit(const JSDescription &joinsplit)
|
||||||
{
|
{
|
||||||
struct timeval tv_start;
|
struct timeval tv_start;
|
||||||
timer_start(tv_start);
|
timer_start(tv_start);
|
||||||
uint256 joinSplitPubKey;
|
Ed25519VerificationKey joinSplitPubKey;
|
||||||
auto verifier = ProofVerifier::Strict();
|
auto verifier = ProofVerifier::Strict();
|
||||||
verifier.VerifySprout(joinsplit, joinSplitPubKey);
|
verifier.VerifySprout(joinsplit, joinSplitPubKey);
|
||||||
return timer_stop(tv_start);
|
return timer_stop(tv_start);
|
||||||
|
@ -161,8 +164,7 @@ double benchmark_solve_equihash()
|
||||||
EhInitialiseState(n, k, eh_state);
|
EhInitialiseState(n, k, eh_state);
|
||||||
crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
|
crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
|
||||||
|
|
||||||
uint256 nonce;
|
uint256 nonce = GetRandHash();
|
||||||
randombytes_buf(nonce.begin(), 32);
|
|
||||||
crypto_generichash_blake2b_update(&eh_state,
|
crypto_generichash_blake2b_update(&eh_state,
|
||||||
nonce.begin(),
|
nonce.begin(),
|
||||||
nonce.size());
|
nonce.size());
|
||||||
|
|
Loading…
Reference in New Issue