rust: Migrate Ed25519 FFI to `cxx`
This commit is contained in:
parent
035e21a610
commit
b1dc94249c
|
@ -52,16 +52,19 @@ endif
|
|||
|
||||
CXXBRIDGE_RS = \
|
||||
rust/src/blake2b.rs \
|
||||
rust/src/ed25519.rs \
|
||||
rust/src/equihash.rs \
|
||||
rust/src/streams.rs \
|
||||
rust/src/bridge.rs
|
||||
CXXBRIDGE_H = \
|
||||
rust/gen/include/rust/blake2b.h \
|
||||
rust/gen/include/rust/ed25519.h \
|
||||
rust/gen/include/rust/equihash.h \
|
||||
rust/gen/include/rust/streams.h \
|
||||
rust/gen/include/rust/bridge.h
|
||||
CXXBRIDGE_CPP = \
|
||||
rust/gen/src/blake2b.cpp \
|
||||
rust/gen/src/ed25519.cpp \
|
||||
rust/gen/src/equihash.cpp \
|
||||
rust/gen/src/streams.cpp \
|
||||
rust/gen/src/bridge.cpp
|
||||
|
|
|
@ -80,20 +80,20 @@ static void ECDSA(benchmark::State& state)
|
|||
|
||||
static void JoinSplitSig(benchmark::State& state)
|
||||
{
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
Ed25519SigningKey joinSplitPrivKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
ed25519::SigningKey joinSplitPrivKey;
|
||||
uint256 dataToBeSigned;
|
||||
Ed25519Signature joinSplitSig;
|
||||
ed25519::Signature joinSplitSig;
|
||||
|
||||
ed25519_generate_keypair(&joinSplitPrivKey, &joinSplitPubKey);
|
||||
ed25519_sign(&joinSplitPrivKey, dataToBeSigned.begin(), 32, &joinSplitSig);
|
||||
ed25519::generate_keypair(joinSplitPrivKey, joinSplitPubKey);
|
||||
ed25519::sign(joinSplitPrivKey, {dataToBeSigned.begin(), 32}, joinSplitSig);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
// Declared with warn_unused_result.
|
||||
auto res = ed25519_verify(
|
||||
&joinSplitPubKey,
|
||||
&joinSplitSig,
|
||||
dataToBeSigned.begin(), 32);
|
||||
auto res = ed25519::verify(
|
||||
joinSplitPubKey,
|
||||
joinSplitSig,
|
||||
{dataToBeSigned.begin(), 32});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,8 +107,8 @@ CMutableTransaction GetValidTransaction(uint32_t consensusBranchId=SPROUT_BRANCH
|
|||
|
||||
void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranchId) {
|
||||
// Generate an ephemeral keypair.
|
||||
Ed25519SigningKey joinSplitPrivKey;
|
||||
ed25519_generate_keypair(&joinSplitPrivKey, &mtx.joinSplitPubKey);
|
||||
ed25519::SigningKey joinSplitPrivKey;
|
||||
ed25519::generate_keypair(joinSplitPrivKey, mtx.joinSplitPubKey);
|
||||
|
||||
// Compute the correct hSig.
|
||||
// TODO: #966.
|
||||
|
@ -126,10 +126,10 @@ void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranch
|
|||
}
|
||||
|
||||
// Add the signature
|
||||
assert(ed25519_sign(
|
||||
&joinSplitPrivKey,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&mtx.joinSplitSig));
|
||||
ed25519::sign(
|
||||
joinSplitPrivKey,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
mtx.joinSplitSig);
|
||||
}
|
||||
|
||||
TEST(ChecktransactionTests, ValidTransaction) {
|
||||
|
@ -856,7 +856,7 @@ TEST(ChecktransactionTests, SaplingSproutInputSumsTooLarge) {
|
|||
{
|
||||
// create JSDescription
|
||||
uint256 rt;
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
||||
libzcash::JSInput(),
|
||||
libzcash::JSInput()
|
||||
|
|
|
@ -14,11 +14,11 @@ void TestLibsodiumEd25519SignatureVerification(
|
|||
{
|
||||
SCOPED_TRACE(scope);
|
||||
|
||||
Ed25519VerificationKey vk;
|
||||
std::copy(pubkey.begin(), pubkey.end(), vk.bytes);
|
||||
ed25519::VerificationKey vk;
|
||||
std::copy(pubkey.begin(), pubkey.end(), vk.bytes.begin());
|
||||
|
||||
Ed25519Signature signature;
|
||||
std::copy(sig.begin(), sig.end(), signature.bytes);
|
||||
ed25519::Signature signature;
|
||||
std::copy(sig.begin(), sig.end(), signature.bytes.begin());
|
||||
|
||||
EXPECT_EQ(
|
||||
crypto_sign_verify_detached(
|
||||
|
@ -28,7 +28,7 @@ void TestLibsodiumEd25519SignatureVerification(
|
|||
0);
|
||||
|
||||
EXPECT_EQ(
|
||||
ed25519_verify(&vk, &signature, (const unsigned char*)msg.data(), msg.size()),
|
||||
ed25519::verify(vk, signature, {(const unsigned char*)msg.data(), msg.size()}),
|
||||
true);
|
||||
}
|
||||
|
||||
|
@ -42,11 +42,11 @@ void ZIP215Check(
|
|||
std::vector<unsigned char> pubkey_hex = ParseHex(pubkey);
|
||||
std::vector<unsigned char> sig_hex = ParseHex(sig);
|
||||
|
||||
Ed25519VerificationKey vk;
|
||||
std::copy(pubkey_hex.begin(), pubkey_hex.end(), vk.bytes);
|
||||
ed25519::VerificationKey vk;
|
||||
std::copy(pubkey_hex.begin(), pubkey_hex.end(), vk.bytes.begin());
|
||||
|
||||
Ed25519Signature signature;
|
||||
std::copy(sig_hex.begin(), sig_hex.end(), signature.bytes);
|
||||
ed25519::Signature signature;
|
||||
std::copy(sig_hex.begin(), sig_hex.end(), signature.bytes.begin());
|
||||
|
||||
std::string msg("Zcash");
|
||||
|
||||
|
@ -64,7 +64,7 @@ void ZIP215Check(
|
|||
expected_legacy);
|
||||
|
||||
EXPECT_EQ(
|
||||
ed25519_verify(&vk, &signature, (const unsigned char*)msg.data(), msg.size()),
|
||||
ed25519::verify(vk, signature, {(const unsigned char*)msg.data(), msg.size()}),
|
||||
valid_zip215);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include <array>
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
using namespace libzcash;
|
||||
|
||||
|
@ -29,7 +29,7 @@ using namespace libzcash;
|
|||
JSDescription makeSproutProof(
|
||||
std::array<JSInput, 2>& inputs,
|
||||
std::array<JSOutput, 2>& outputs,
|
||||
const Ed25519VerificationKey& joinSplitPubKey,
|
||||
const ed25519::VerificationKey& joinSplitPubKey,
|
||||
uint64_t vpub_old,
|
||||
uint64_t vpub_new,
|
||||
const uint256& rt
|
||||
|
@ -39,7 +39,7 @@ JSDescription makeSproutProof(
|
|||
|
||||
bool verifySproutProof(
|
||||
const JSDescription& jsdesc,
|
||||
const Ed25519VerificationKey& joinSplitPubKey
|
||||
const ed25519::VerificationKey& joinSplitPubKey
|
||||
)
|
||||
{
|
||||
auto verifier = ProofVerifier::Strict();
|
||||
|
@ -62,8 +62,8 @@ void test_full_api()
|
|||
// Set up a JoinSplit description
|
||||
uint64_t vpub_old = 10;
|
||||
uint64_t vpub_new = 0;
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
GetRandBytes(joinSplitPubKey.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
GetRandBytes(joinSplitPubKey.bytes.data(), joinSplitPubKey.bytes.size());
|
||||
uint256 rt = tree.root();
|
||||
JSDescription jsdesc;
|
||||
|
||||
|
@ -122,8 +122,8 @@ void test_full_api()
|
|||
vpub_old = 0;
|
||||
vpub_new = 1;
|
||||
rt = tree.root();
|
||||
Ed25519VerificationKey joinSplitPubKey2;
|
||||
GetRandBytes(joinSplitPubKey2.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||
ed25519::VerificationKey joinSplitPubKey2;
|
||||
GetRandBytes(joinSplitPubKey2.bytes.data(), joinSplitPubKey2.bytes.size());
|
||||
|
||||
{
|
||||
std::array<JSInput, 2> inputs = {
|
||||
|
@ -171,8 +171,8 @@ void invokeAPI(
|
|||
) {
|
||||
uint256 ephemeralKey;
|
||||
uint256 randomSeed;
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
GetRandBytes(joinSplitPubKey.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
GetRandBytes(joinSplitPubKey.bytes.data(), joinSplitPubKey.bytes.size());
|
||||
std::array<uint256, 2> macs;
|
||||
std::array<uint256, 2> nullifiers;
|
||||
std::array<uint256, 2> commitments;
|
||||
|
@ -283,9 +283,9 @@ for test_input in TEST_VECTORS:
|
|||
};
|
||||
|
||||
for (std::vector<std::string>& v : tests) {
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
auto pubKeyBytes = uint256S(v[3]);
|
||||
std::copy(pubKeyBytes.begin(), pubKeyBytes.end(), joinSplitPubKey.bytes);
|
||||
std::copy(pubKeyBytes.begin(), pubKeyBytes.end(), joinSplitPubKey.bytes.begin());
|
||||
auto expected = ZCJoinSplit::h_sig(
|
||||
uint256S(v[0]),
|
||||
{uint256S(v[1]), uint256S(v[2])},
|
||||
|
@ -617,7 +617,7 @@ TEST(Joinsplit, BasicJoinsplitVerification)
|
|||
auto witness = merkleTree.witness();
|
||||
|
||||
// create JSDescription
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
||||
libzcash::JSInput(witness, note, k),
|
||||
libzcash::JSInput() // dummy input of zero value
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <array>
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
TEST(Transaction, JSDescriptionRandomized) {
|
||||
// construct a merkle tree
|
||||
|
@ -31,7 +31,7 @@ TEST(Transaction, JSDescriptionRandomized) {
|
|||
auto witness = merkleTree.witness();
|
||||
|
||||
// create JSDescription
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
||||
libzcash::JSInput(witness, note, k),
|
||||
libzcash::JSInput() // dummy input of zero value
|
||||
|
|
|
@ -1333,15 +1333,15 @@ bool ContextualCheckShieldedInputs(
|
|||
|
||||
if (!tx.vJoinSplit.empty())
|
||||
{
|
||||
if (!ed25519_verify(&tx.joinSplitPubKey, &tx.joinSplitSig, dataToBeSigned.begin(), 32)) {
|
||||
if (!ed25519::verify(tx.joinSplitPubKey, tx.joinSplitSig, {dataToBeSigned.begin(), 32})) {
|
||||
// Check whether the failure was caused by an outdated consensus
|
||||
// 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
|
||||
// users creating transactions will notice their transactions
|
||||
// failing before a second network upgrade occurs.
|
||||
if (ed25519_verify(&tx.joinSplitPubKey,
|
||||
&tx.joinSplitSig,
|
||||
prevDataToBeSigned.begin(), 32)) {
|
||||
if (ed25519::verify(tx.joinSplitPubKey,
|
||||
tx.joinSplitSig,
|
||||
{prevDataToBeSigned.begin(), 32})) {
|
||||
return state.DoS(
|
||||
dosLevelPotentiallyRelaxing, false, REJECT_INVALID, strprintf(
|
||||
"old-consensus-branch-id (Expected %s, found %s)",
|
||||
|
|
|
@ -255,8 +255,8 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
|
|||
*const_cast<std::vector<OutputDescription>*>(&vShieldedOutput) = tx.vShieldedOutput;
|
||||
orchardBundle = tx.orchardBundle;
|
||||
*const_cast<std::vector<JSDescription>*>(&vJoinSplit) = tx.vJoinSplit;
|
||||
*const_cast<Ed25519VerificationKey*>(&joinSplitPubKey) = tx.joinSplitPubKey;
|
||||
*const_cast<Ed25519Signature*>(&joinSplitSig) = tx.joinSplitSig;
|
||||
*const_cast<ed25519::VerificationKey*>(&joinSplitPubKey) = tx.joinSplitPubKey;
|
||||
*const_cast<ed25519::Signature*>(&joinSplitSig) = tx.joinSplitSig;
|
||||
*const_cast<binding_sig_t*>(&bindingSig) = tx.bindingSig;
|
||||
*const_cast<uint256*>(&wtxid.hash) = tx.wtxid.hash;
|
||||
*const_cast<uint256*>(&wtxid.authDigest) = tx.wtxid.authDigest;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "zcash/Zcash.h"
|
||||
#include "zcash/Proof.hpp"
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
#include <primitives/orchard.h>
|
||||
|
||||
// Overwinter transaction version group id
|
||||
|
@ -772,8 +772,8 @@ public:
|
|||
const std::vector<SpendDescription> vShieldedSpend;
|
||||
const std::vector<OutputDescription> vShieldedOutput;
|
||||
const std::vector<JSDescription> vJoinSplit;
|
||||
const Ed25519VerificationKey joinSplitPubKey;
|
||||
const Ed25519Signature joinSplitSig;
|
||||
const ed25519::VerificationKey joinSplitPubKey;
|
||||
const ed25519::Signature joinSplitSig;
|
||||
const binding_sig_t bindingSig = {{0}};
|
||||
|
||||
/** Construct a CTransaction that qualifies as IsNull() */
|
||||
|
@ -888,8 +888,8 @@ public:
|
|||
auto os = WithVersion(&s, static_cast<int>(header));
|
||||
::SerReadWrite(os, *const_cast<std::vector<JSDescription>*>(&vJoinSplit), ser_action);
|
||||
if (vJoinSplit.size() > 0) {
|
||||
READWRITE(*const_cast<Ed25519VerificationKey*>(&joinSplitPubKey));
|
||||
READWRITE(*const_cast<Ed25519Signature*>(&joinSplitSig));
|
||||
READWRITE(*const_cast<ed25519::VerificationKey*>(&joinSplitPubKey));
|
||||
READWRITE(*const_cast<ed25519::Signature*>(&joinSplitSig));
|
||||
}
|
||||
}
|
||||
if ((isSaplingV4 || isFuture) && !(vShieldedSpend.empty() && vShieldedOutput.empty())) {
|
||||
|
@ -1021,8 +1021,8 @@ struct CMutableTransaction
|
|||
std::vector<OutputDescription> vShieldedOutput;
|
||||
OrchardBundle orchardBundle;
|
||||
std::vector<JSDescription> vJoinSplit;
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
Ed25519Signature joinSplitSig;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
ed25519::Signature joinSplitSig;
|
||||
CTransaction::binding_sig_t bindingSig = {{0}};
|
||||
|
||||
CMutableTransaction();
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
class SproutProofVerifier
|
||||
{
|
||||
ProofVerifier& verifier;
|
||||
const Ed25519VerificationKey& joinSplitPubKey;
|
||||
const ed25519::VerificationKey& joinSplitPubKey;
|
||||
const JSDescription& jsdesc;
|
||||
|
||||
public:
|
||||
SproutProofVerifier(
|
||||
ProofVerifier& verifier,
|
||||
const Ed25519VerificationKey& joinSplitPubKey,
|
||||
const ed25519::VerificationKey& joinSplitPubKey,
|
||||
const JSDescription& jsdesc
|
||||
) : jsdesc(jsdesc), verifier(verifier), joinSplitPubKey(joinSplitPubKey) {}
|
||||
|
||||
|
@ -60,7 +60,7 @@ ProofVerifier ProofVerifier::Disabled() {
|
|||
|
||||
bool ProofVerifier::VerifySprout(
|
||||
const JSDescription& jsdesc,
|
||||
const Ed25519VerificationKey& joinSplitPubKey
|
||||
const ed25519::VerificationKey& joinSplitPubKey
|
||||
) {
|
||||
if (!perform_verification) {
|
||||
return true;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <primitives/transaction.h>
|
||||
#include <uint256.h>
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
class ProofVerifier {
|
||||
private:
|
||||
|
@ -35,7 +35,7 @@ public:
|
|||
// Verifies that the JoinSplit proof is correct.
|
||||
bool VerifySprout(
|
||||
const JSDescription& jsdesc,
|
||||
const Ed25519VerificationKey& joinSplitPubKey
|
||||
const ed25519::VerificationKey& joinSplitPubKey
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -309,12 +309,12 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
|
|||
// it is byte-flipped in the RPC output.
|
||||
uint256 joinSplitPubKey;
|
||||
std::copy(
|
||||
tx.joinSplitPubKey.bytes,
|
||||
tx.joinSplitPubKey.bytes + ED25519_VERIFICATION_KEY_LEN,
|
||||
tx.joinSplitPubKey.bytes.begin(),
|
||||
tx.joinSplitPubKey.bytes.end(),
|
||||
joinSplitPubKey.begin());
|
||||
entry.pushKV("joinSplitPubKey", joinSplitPubKey.GetHex());
|
||||
entry.pushKV("joinSplitSig",
|
||||
HexStr(tx.joinSplitSig.bytes, tx.joinSplitSig.bytes + ED25519_SIGNATURE_LEN));
|
||||
HexStr(tx.joinSplitSig.bytes.begin(), tx.joinSplitSig.bytes.end()));
|
||||
}
|
||||
|
||||
if (!hashBlock.IsNull()) {
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
// Copyright (c) 2020-2023 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#ifndef ZCASH_RUST_INCLUDE_RUST_ED25519_H
|
||||
#define ZCASH_RUST_INCLUDE_RUST_ED25519_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 // ZCASH_RUST_INCLUDE_RUST_ED25519_H
|
|
@ -1,56 +0,0 @@
|
|||
// Copyright (c) 2020-2023 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#ifndef ZCASH_RUST_INCLUDE_RUST_ED25519_TYPES_H
|
||||
#define ZCASH_RUST_INCLUDE_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 // ZCASH_RUST_INCLUDE_RUST_ED25519_TYPES_H
|
|
@ -3,65 +3,67 @@
|
|||
// 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();
|
||||
#[cxx::bridge(namespace = "ed25519")]
|
||||
mod ffi {
|
||||
struct SigningKey {
|
||||
bytes: [u8; 32],
|
||||
}
|
||||
|
||||
struct VerificationKey {
|
||||
bytes: [u8; 32],
|
||||
}
|
||||
|
||||
struct Signature {
|
||||
bytes: [u8; 64],
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
fn generate_keypair(sk: &mut SigningKey, vk: &mut VerificationKey);
|
||||
fn sign(sk: &SigningKey, msg: &[u8], signature: &mut Signature);
|
||||
fn verify(vk: &VerificationKey, signature: &Signature, msg: &[u8]) -> bool;
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a new Ed25519 keypair.
|
||||
fn generate_keypair(sk: &mut ffi::SigningKey, vk: &mut ffi::VerificationKey) {
|
||||
let signing_key = SigningKey::new(OsRng);
|
||||
|
||||
*sk = signing_key.into();
|
||||
*vk = VerificationKey::from(&signing_key).into();
|
||||
sk.bytes = signing_key.into();
|
||||
vk.bytes = 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
|
||||
/// Creates a signature on msg using the given signing key.
|
||||
fn sign(sk: &ffi::SigningKey, msg: &[u8], signature: &mut ffi::Signature) {
|
||||
let sk = SigningKey::from(sk.bytes);
|
||||
signature.bytes = sk.sign(msg).into();
|
||||
}
|
||||
|
||||
#[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()) {
|
||||
/// 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.
|
||||
fn verify(vk: &ffi::VerificationKey, signature: &ffi::Signature, msg: &[u8]) -> bool {
|
||||
let vk = match VerificationKey::try_from(vk.bytes) {
|
||||
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) };
|
||||
let signature = Signature::from(signature.bytes);
|
||||
|
||||
vk.verify(&signature, msg).is_ok()
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <vector>
|
||||
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
#include "prevector.h"
|
||||
|
||||
|
@ -588,22 +588,22 @@ template<typename Stream, typename T> void Serialize(Stream& os, const std::uniq
|
|||
template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
|
||||
|
||||
/**
|
||||
* Ed25519SigningKey
|
||||
* ed25519::SigningKey
|
||||
*/
|
||||
template<typename Stream> void Serialize(Stream& os, const Ed25519SigningKey& item);
|
||||
template<typename Stream> void Unserialize(Stream& is, Ed25519SigningKey& item);
|
||||
template<typename Stream> void Serialize(Stream& os, const ed25519::SigningKey& item);
|
||||
template<typename Stream> void Unserialize(Stream& is, ed25519::SigningKey& item);
|
||||
|
||||
/**
|
||||
* Ed25519VerificationKey
|
||||
* ed25519::VerificationKey
|
||||
*/
|
||||
template<typename Stream> void Serialize(Stream& os, const Ed25519VerificationKey& item);
|
||||
template<typename Stream> void Unserialize(Stream& is, Ed25519VerificationKey& item);
|
||||
template<typename Stream> void Serialize(Stream& os, const ed25519::VerificationKey& item);
|
||||
template<typename Stream> void Unserialize(Stream& is, ed25519::VerificationKey& item);
|
||||
|
||||
/**
|
||||
* Ed25519Signature
|
||||
* ed25519::Signature
|
||||
*/
|
||||
template<typename Stream> void Serialize(Stream& os, const Ed25519Signature& item);
|
||||
template<typename Stream> void Unserialize(Stream& is, Ed25519Signature& item);
|
||||
template<typename Stream> void Serialize(Stream& os, const ed25519::Signature& item);
|
||||
template<typename Stream> void Unserialize(Stream& is, ed25519::Signature& item);
|
||||
|
||||
|
||||
|
||||
|
@ -976,52 +976,52 @@ void Unserialize(Stream& is, std::shared_ptr<const T>& p)
|
|||
|
||||
|
||||
/**
|
||||
* Ed25519SigningKey
|
||||
* ed25519::SigningKey
|
||||
*/
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& os, const Ed25519SigningKey& sk)
|
||||
void Serialize(Stream& os, const ed25519::SigningKey& sk)
|
||||
{
|
||||
os.write((char*)sk.bytes, ED25519_SIGNING_KEY_LEN);
|
||||
Serialize(os, sk.bytes);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& is, Ed25519SigningKey& sk)
|
||||
void Unserialize(Stream& is, ed25519::SigningKey& sk)
|
||||
{
|
||||
is.read((char*)sk.bytes, ED25519_SIGNING_KEY_LEN);
|
||||
Unserialize(is, sk.bytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Ed25519VerificationKey
|
||||
* ed25519::VerificationKey
|
||||
*/
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& os, const Ed25519VerificationKey& vk)
|
||||
void Serialize(Stream& os, const ed25519::VerificationKey& vk)
|
||||
{
|
||||
os.write((char*)vk.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||
Serialize(os, vk.bytes);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& is, Ed25519VerificationKey& vk)
|
||||
void Unserialize(Stream& is, ed25519::VerificationKey& vk)
|
||||
{
|
||||
is.read((char*)vk.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||
Unserialize(is, vk.bytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Ed25519Signature
|
||||
* ed25519::Signature
|
||||
*/
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& os, const Ed25519Signature& sig)
|
||||
void Serialize(Stream& os, const ed25519::Signature& sig)
|
||||
{
|
||||
os.write((char*)sig.bytes, ED25519_SIGNATURE_LEN);
|
||||
Serialize(os, sig.bytes);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& is, Ed25519Signature& sig)
|
||||
void Unserialize(Stream& is, ed25519::Signature& sig)
|
||||
{
|
||||
is.read((char*)sig.bytes, ED25519_SIGNATURE_LEN);
|
||||
Unserialize(is, sig.bytes);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
|
|||
}
|
||||
|
||||
// Blank out the joinsplit signature.
|
||||
memset(&txTmp.joinSplitSig.bytes, 0, ED25519_SIGNATURE_LEN);
|
||||
txTmp.joinSplitSig.bytes.fill(0);
|
||||
|
||||
// Serialize and hash
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
|
@ -184,8 +184,8 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co
|
|||
tx.vJoinSplit.push_back(jsdesc);
|
||||
}
|
||||
|
||||
Ed25519SigningKey joinSplitPrivKey;
|
||||
ed25519_generate_keypair(&joinSplitPrivKey, &tx.joinSplitPubKey);
|
||||
ed25519::SigningKey joinSplitPrivKey;
|
||||
ed25519::generate_keypair(joinSplitPrivKey, tx.joinSplitPubKey);
|
||||
|
||||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
|
@ -193,10 +193,10 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co
|
|||
PrecomputedTransactionData txdata(signTx, {});
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||
|
||||
assert(ed25519_sign(
|
||||
&joinSplitPrivKey,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&tx.joinSplitSig));
|
||||
ed25519::sign(
|
||||
joinSplitPrivKey,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
tx.joinSplitSig);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -365,8 +365,8 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa
|
|||
AssumeShieldedInputsExistAndAreSpendable baseView;
|
||||
CCoinsViewCache view(&baseView);
|
||||
|
||||
Ed25519SigningKey joinSplitPrivKey;
|
||||
ed25519_generate_keypair(&joinSplitPrivKey, &newTx.joinSplitPubKey);
|
||||
ed25519::SigningKey joinSplitPrivKey;
|
||||
ed25519::generate_keypair(joinSplitPrivKey, newTx.joinSplitPubKey);
|
||||
|
||||
// No joinsplits, vin and vout, means it should be invalid.
|
||||
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
|
||||
|
@ -404,10 +404,10 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa
|
|||
CTransaction signTx(newTx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||
|
||||
assert(ed25519_sign(
|
||||
&joinSplitPrivKey,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&newTx.joinSplitSig));
|
||||
ed25519::sign(
|
||||
joinSplitPrivKey,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
newTx.joinSplitSig);
|
||||
|
||||
state = CValidationState();
|
||||
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
||||
|
|
|
@ -617,8 +617,8 @@ TransactionBuilderResult TransactionBuilder::Build()
|
|||
// Sprout JoinSplits
|
||||
//
|
||||
|
||||
Ed25519SigningKey joinSplitPrivKey;
|
||||
ed25519_generate_keypair(&joinSplitPrivKey, &mtx.joinSplitPubKey);
|
||||
ed25519::SigningKey joinSplitPrivKey;
|
||||
ed25519::generate_keypair(joinSplitPrivKey, mtx.joinSplitPubKey);
|
||||
|
||||
// Create Sprout JSDescriptions
|
||||
if (!jsInputs.empty() || !jsOutputs.empty()) {
|
||||
|
@ -676,19 +676,16 @@ TransactionBuilderResult TransactionBuilder::Build()
|
|||
mtx.bindingSig);
|
||||
|
||||
// Create Sprout joinSplitSig
|
||||
if (!ed25519_sign(
|
||||
&joinSplitPrivKey,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&mtx.joinSplitSig))
|
||||
{
|
||||
return TransactionBuilderResult("Failed to create Sprout joinSplitSig");
|
||||
}
|
||||
ed25519::sign(
|
||||
joinSplitPrivKey,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
mtx.joinSplitSig);
|
||||
|
||||
// Sanity check Sprout joinSplitSig
|
||||
if (!ed25519_verify(
|
||||
&mtx.joinSplitPubKey,
|
||||
&mtx.joinSplitSig,
|
||||
dataToBeSigned.begin(), 32))
|
||||
if (!ed25519::verify(
|
||||
mtx.joinSplitPubKey,
|
||||
mtx.joinSplitSig,
|
||||
{dataToBeSigned.begin(), 32}))
|
||||
{
|
||||
return TransactionBuilderResult("Sprout joinSplitSig sanity check failed");
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/builder.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
#define NO_MEMO {{0xF6}}
|
||||
|
||||
|
@ -208,7 +209,7 @@ struct OutputDescriptionInfo {
|
|||
};
|
||||
|
||||
struct JSDescriptionInfo {
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
uint256 anchor;
|
||||
// We store references to these so they are correctly randomised for the caller.
|
||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs;
|
||||
|
@ -217,7 +218,7 @@ struct JSDescriptionInfo {
|
|||
CAmount vpub_new;
|
||||
|
||||
JSDescriptionInfo(
|
||||
Ed25519VerificationKey joinSplitPubKey,
|
||||
ed25519::VerificationKey joinSplitPubKey,
|
||||
uint256 anchor,
|
||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
||||
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
||||
|
|
|
@ -41,8 +41,8 @@ CMutableTransaction GetValidSproutReceiveTransaction(
|
|||
allPrevOutputs.resize(mtx.vin.size());
|
||||
|
||||
// Generate an ephemeral keypair.
|
||||
Ed25519SigningKey joinSplitPrivKey;
|
||||
ed25519_generate_keypair(&joinSplitPrivKey, &mtx.joinSplitPubKey);
|
||||
ed25519::SigningKey joinSplitPrivKey;
|
||||
ed25519::generate_keypair(joinSplitPrivKey, mtx.joinSplitPubKey);
|
||||
|
||||
std::array<libzcash::JSInput, 2> inputs = {
|
||||
libzcash::JSInput(), // dummy input
|
||||
|
@ -76,10 +76,10 @@ CMutableTransaction GetValidSproutReceiveTransaction(
|
|||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||
|
||||
// Add the signature
|
||||
assert(ed25519_sign(
|
||||
&joinSplitPrivKey,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&mtx.joinSplitSig));
|
||||
ed25519::sign(
|
||||
joinSplitPrivKey,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
mtx.joinSplitSig);
|
||||
|
||||
return mtx;
|
||||
}
|
||||
|
@ -143,8 +143,8 @@ CWalletTx GetValidSproutSpend(const libzcash::SproutSpendingKey& sk,
|
|||
mtx.vout[1].nValue = 0;
|
||||
|
||||
// Generate an ephemeral keypair.
|
||||
Ed25519SigningKey joinSplitPrivKey;
|
||||
ed25519_generate_keypair(&joinSplitPrivKey, &mtx.joinSplitPubKey);
|
||||
ed25519::SigningKey joinSplitPrivKey;
|
||||
ed25519::generate_keypair(joinSplitPrivKey, mtx.joinSplitPubKey);
|
||||
|
||||
// Fake tree for the unused witness
|
||||
SproutMerkleTree tree;
|
||||
|
@ -193,10 +193,10 @@ CWalletTx GetValidSproutSpend(const libzcash::SproutSpendingKey& sk,
|
|||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||
|
||||
// Add the signature
|
||||
assert(ed25519_sign(
|
||||
&joinSplitPrivKey,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&mtx.joinSplitSig));
|
||||
ed25519::sign(
|
||||
joinSplitPrivKey,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
mtx.joinSplitSig);
|
||||
CTransaction tx {mtx};
|
||||
CWalletTx wtx {NULL, tx};
|
||||
return wtx;
|
||||
|
|
|
@ -401,7 +401,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||
|
||||
// Prepare raw transaction to handle JoinSplits
|
||||
CMutableTransaction mtx(tx_);
|
||||
ed25519_generate_keypair(&joinSplitPrivKey_, &joinSplitPubKey_);
|
||||
ed25519::generate_keypair(joinSplitPrivKey_, joinSplitPubKey_);
|
||||
mtx.joinSplitPubKey = joinSplitPubKey_;
|
||||
tx_ = CTransaction(mtx);
|
||||
|
||||
|
@ -856,19 +856,16 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
|||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_, txdata);
|
||||
|
||||
// Add the signature
|
||||
if (!ed25519_sign(
|
||||
&joinSplitPrivKey_,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&mtx.joinSplitSig))
|
||||
{
|
||||
throw std::runtime_error("ed25519_sign failed");
|
||||
}
|
||||
ed25519::sign(
|
||||
joinSplitPrivKey_,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
mtx.joinSplitSig);
|
||||
|
||||
// Sanity check
|
||||
if (!ed25519_verify(
|
||||
&mtx.joinSplitPubKey,
|
||||
&mtx.joinSplitSig,
|
||||
dataToBeSigned.begin(), 32))
|
||||
if (!ed25519::verify(
|
||||
mtx.joinSplitPubKey,
|
||||
mtx.joinSplitSig,
|
||||
{dataToBeSigned.begin(), 32}))
|
||||
{
|
||||
throw std::runtime_error("ed25519_verify failed");
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include <univalue.h>
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
using namespace libzcash;
|
||||
|
||||
|
@ -95,8 +95,8 @@ private:
|
|||
PaymentAddress toPaymentAddress_;
|
||||
std::string memo_;
|
||||
|
||||
Ed25519VerificationKey joinSplitPubKey_;
|
||||
Ed25519SigningKey joinSplitPrivKey_;
|
||||
ed25519::VerificationKey joinSplitPubKey_;
|
||||
ed25519::SigningKey joinSplitPrivKey_;
|
||||
|
||||
// The key is the result string from calling JSOutPoint::ToString()
|
||||
std::unordered_map<std::string, MergeToAddressWitnessAnchorData> jsopWitnessAnchorMap;
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
using namespace libzcash;
|
||||
|
||||
AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
|
||||
#include <univalue.h>
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
|
||||
using namespace libzcash;
|
||||
|
||||
class AsyncRPCOperation_sendmany : public AsyncRPCOperation {
|
||||
|
|
|
@ -255,7 +255,7 @@ bool ShieldToAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) co
|
|||
|
||||
// Prepare raw transaction to handle JoinSplits
|
||||
CMutableTransaction mtx(m_op->tx_);
|
||||
ed25519_generate_keypair(&m_op->joinSplitPrivKey_, &m_op->joinSplitPubKey_);
|
||||
ed25519::generate_keypair(m_op->joinSplitPrivKey_, m_op->joinSplitPubKey_);
|
||||
mtx.joinSplitPubKey = m_op->joinSplitPubKey_;
|
||||
m_op->tx_ = CTransaction(mtx);
|
||||
|
||||
|
@ -379,19 +379,16 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
|
|||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||
|
||||
// Add the signature
|
||||
if (!ed25519_sign(
|
||||
&joinSplitPrivKey_,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&mtx.joinSplitSig))
|
||||
{
|
||||
throw std::runtime_error("ed25519_sign failed");
|
||||
}
|
||||
ed25519::sign(
|
||||
joinSplitPrivKey_,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
mtx.joinSplitSig);
|
||||
|
||||
// Sanity check
|
||||
if (!ed25519_verify(
|
||||
&mtx.joinSplitPubKey,
|
||||
&mtx.joinSplitSig,
|
||||
dataToBeSigned.begin(), 32))
|
||||
if (!ed25519::verify(
|
||||
mtx.joinSplitPubKey,
|
||||
mtx.joinSplitSig,
|
||||
{dataToBeSigned.begin(), 32}))
|
||||
{
|
||||
throw std::runtime_error("ed25519_verify failed");
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include <univalue.h>
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
using namespace libzcash;
|
||||
|
||||
|
@ -73,8 +73,8 @@ private:
|
|||
CAmount fee_;
|
||||
PaymentAddress tozaddr_;
|
||||
|
||||
Ed25519VerificationKey joinSplitPubKey_;
|
||||
Ed25519SigningKey joinSplitPrivKey_;
|
||||
ed25519::VerificationKey joinSplitPubKey_;
|
||||
ed25519::SigningKey joinSplitPrivKey_;
|
||||
|
||||
std::vector<ShieldCoinbaseUTXO> inputs_;
|
||||
|
||||
|
|
|
@ -97,9 +97,9 @@ TEST(paymentdisclosure, mainnet) {
|
|||
|
||||
for (int i=0; i<NUM_TRIES; i++) {
|
||||
// Generate an ephemeral keypair for joinsplit sig.
|
||||
Ed25519SigningKey joinSplitPrivKey;
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
ed25519_generate_keypair(&joinSplitPrivKey, &joinSplitPubKey);
|
||||
ed25519::SigningKey joinSplitPrivKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
ed25519::generate_keypair(joinSplitPrivKey, joinSplitPubKey);
|
||||
|
||||
// Create payment disclosure key and info data to store in test database
|
||||
size_t js = GetRandHash().GetCheapHash() % std::numeric_limits<size_t>::max();
|
||||
|
@ -118,7 +118,7 @@ TEST(paymentdisclosure, mainnet) {
|
|||
|
||||
// Modify this local variable and confirm it no longer matches
|
||||
info2.esk = GetRandHash();
|
||||
GetRandBytes(info2.joinSplitPrivKey.bytes, ED25519_VERIFICATION_KEY_LEN);
|
||||
GetRandBytes(info2.joinSplitPrivKey.bytes.data(), info2.joinSplitPrivKey.bytes.size());
|
||||
info2.zaddr = libzcash::SproutSpendingKey::random().address();
|
||||
ASSERT_NE(info, info2);
|
||||
|
||||
|
@ -136,20 +136,17 @@ TEST(paymentdisclosure, mainnet) {
|
|||
uint256 dataToBeSigned = SerializeHash(payload, SER_GETHASH, 0);
|
||||
|
||||
// Compute the payload signature
|
||||
Ed25519Signature payloadSig;
|
||||
if (!ed25519_sign(
|
||||
&joinSplitPrivKey,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&payloadSig))
|
||||
{
|
||||
throw std::runtime_error("ed25519_sign failed");
|
||||
}
|
||||
ed25519::Signature payloadSig;
|
||||
ed25519::sign(
|
||||
joinSplitPrivKey,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
payloadSig);
|
||||
|
||||
// Sanity check
|
||||
if (!ed25519_verify(
|
||||
&joinSplitPubKey,
|
||||
&payloadSig,
|
||||
dataToBeSigned.begin(), 32))
|
||||
if (!ed25519::verify(
|
||||
joinSplitPubKey,
|
||||
payloadSig,
|
||||
{dataToBeSigned.begin(), 32}))
|
||||
{
|
||||
throw std::runtime_error("ed25519_verify failed");
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ std::string PaymentDisclosureInfo::ToString() const {
|
|||
}
|
||||
|
||||
std::string PaymentDisclosure::ToString() const {
|
||||
std::string s = HexStr(payloadSig.bytes, payloadSig.bytes + ED25519_SIGNATURE_LEN);
|
||||
std::string s = HexStr(payloadSig.bytes.begin(), payloadSig.bytes.end());
|
||||
return strprintf("PaymentDisclosure(payload=%s, payloadSig=%s)", payload.ToString(), s);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ std::string PaymentDisclosurePayload::ToString() const {
|
|||
}
|
||||
|
||||
PaymentDisclosure::PaymentDisclosure(
|
||||
const Ed25519VerificationKey& joinSplitPubKey,
|
||||
const ed25519::VerificationKey& joinSplitPubKey,
|
||||
const PaymentDisclosureKey& key,
|
||||
const PaymentDisclosureInfo& info,
|
||||
const std::string& message)
|
||||
|
@ -47,23 +47,20 @@ PaymentDisclosure::PaymentDisclosure(
|
|||
LogPrint("paymentdisclosure", "Payment Disclosure: signing raw payload = %s\n", dataToBeSigned.ToString());
|
||||
|
||||
// Compute payload signature member variable
|
||||
if (!ed25519_sign(
|
||||
&info.joinSplitPrivKey,
|
||||
dataToBeSigned.begin(), 32,
|
||||
&payloadSig))
|
||||
{
|
||||
throw std::runtime_error("ed25519_sign failed");
|
||||
}
|
||||
ed25519::sign(
|
||||
info.joinSplitPrivKey,
|
||||
{dataToBeSigned.begin(), 32},
|
||||
payloadSig);
|
||||
|
||||
// Sanity check
|
||||
if (!ed25519_verify(
|
||||
&joinSplitPubKey,
|
||||
&payloadSig,
|
||||
dataToBeSigned.begin(), 32))
|
||||
if (!ed25519::verify(
|
||||
joinSplitPubKey,
|
||||
payloadSig,
|
||||
{dataToBeSigned.begin(), 32}))
|
||||
{
|
||||
throw std::runtime_error("ed25519_verify failed");
|
||||
}
|
||||
|
||||
std::string sigString = HexStr(payloadSig.bytes, payloadSig.bytes + ED25519_SIGNATURE_LEN);
|
||||
std::string sigString = HexStr(payloadSig.bytes.begin(), payloadSig.bytes.end());
|
||||
LogPrint("paymentdisclosure", "Payment Disclosure: signature = %s\n", sigString);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
|
||||
// Ensure that the two different protocol messages, payment disclosure blobs and transactions,
|
||||
|
@ -38,7 +38,7 @@ typedef JSOutPoint PaymentDisclosureKey;
|
|||
struct PaymentDisclosureInfo {
|
||||
uint8_t version; // 0 = experimental, 1 = first production version, etc.
|
||||
uint256 esk; // zcash/NoteEncryption.cpp
|
||||
Ed25519SigningKey joinSplitPrivKey; // primitives/transaction.h
|
||||
ed25519::SigningKey joinSplitPrivKey; // primitives/transaction.h
|
||||
// ed25519 - not tied to implementation e.g. libsodium, see ed25519 rfc
|
||||
|
||||
libzcash::SproutPaymentAddress zaddr;
|
||||
|
@ -46,7 +46,7 @@ struct PaymentDisclosureInfo {
|
|||
PaymentDisclosureInfo() : version(PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL) {
|
||||
}
|
||||
|
||||
PaymentDisclosureInfo(uint8_t v, uint256 esk, Ed25519SigningKey key, libzcash::SproutPaymentAddress zaddr) : version(v), esk(esk), joinSplitPrivKey(key), zaddr(zaddr) { }
|
||||
PaymentDisclosureInfo(uint8_t v, uint256 esk, ed25519::SigningKey key, libzcash::SproutPaymentAddress zaddr) : version(v), esk(esk), joinSplitPrivKey(key), zaddr(zaddr) { }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
|
@ -64,10 +64,7 @@ struct PaymentDisclosureInfo {
|
|||
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.joinSplitPrivKey.bytes == b.joinSplitPrivKey.bytes &&
|
||||
a.zaddr == b.zaddr);
|
||||
}
|
||||
|
||||
|
@ -123,13 +120,13 @@ struct PaymentDisclosurePayload {
|
|||
|
||||
struct PaymentDisclosure {
|
||||
PaymentDisclosurePayload payload;
|
||||
Ed25519Signature payloadSig;
|
||||
ed25519::Signature payloadSig;
|
||||
// We use boost array because serialize doesn't like char buffer, otherwise we could do: unsigned char payloadSig[64];
|
||||
|
||||
PaymentDisclosure() {};
|
||||
PaymentDisclosure(const PaymentDisclosurePayload payload, const Ed25519Signature sig) : payload(payload), payloadSig(sig) {};
|
||||
PaymentDisclosure(const PaymentDisclosurePayload payload, const ed25519::Signature sig) : payload(payload), payloadSig(sig) {};
|
||||
PaymentDisclosure(
|
||||
const Ed25519VerificationKey& joinSplitPubKey,
|
||||
const ed25519::VerificationKey& joinSplitPubKey,
|
||||
const PaymentDisclosureKey& key,
|
||||
const PaymentDisclosureInfo& info,
|
||||
const std::string& message);
|
||||
|
@ -147,10 +144,7 @@ struct PaymentDisclosure {
|
|||
friend bool operator==(const PaymentDisclosure& a, const PaymentDisclosure& b) {
|
||||
return (
|
||||
a.payload == b.payload &&
|
||||
std::equal(
|
||||
a.payloadSig.bytes,
|
||||
a.payloadSig.bytes + ED25519_SIGNATURE_LEN,
|
||||
b.payloadSig.bytes)
|
||||
a.payloadSig.bytes == b.payloadSig.bytes
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -246,17 +246,17 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
|
|||
// it is byte-flipped in the RPC output.
|
||||
uint256 joinSplitPubKey;
|
||||
std::copy(
|
||||
tx.joinSplitPubKey.bytes,
|
||||
tx.joinSplitPubKey.bytes + ED25519_VERIFICATION_KEY_LEN,
|
||||
tx.joinSplitPubKey.bytes.begin(),
|
||||
tx.joinSplitPubKey.bytes.end(),
|
||||
joinSplitPubKey.begin());
|
||||
o.pushKV("joinSplitPubKey", joinSplitPubKey.ToString());
|
||||
|
||||
// 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);
|
||||
bool sigVerified = ed25519_verify(
|
||||
&tx.joinSplitPubKey,
|
||||
&pd.payloadSig,
|
||||
dataToBeSigned.begin(), 32);
|
||||
bool sigVerified = ed25519::verify(
|
||||
tx.joinSplitPubKey,
|
||||
pd.payloadSig,
|
||||
{dataToBeSigned.begin(), 32});
|
||||
o.pushKV("signatureVerified", sigVerified);
|
||||
if (!sigVerified) {
|
||||
errs.push_back("Payment disclosure signature does not match transaction signature");
|
||||
|
|
|
@ -2941,7 +2941,7 @@ UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp)
|
|||
|
||||
LOCK(cs_main);
|
||||
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
uint256 anchor = SproutMerkleTree().root();
|
||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs({JSInput(), JSInput()});
|
||||
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs({JSOutput(), JSOutput()});
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace libzcash {
|
|||
std::array<SproutNote, NumOutputs>& out_notes,
|
||||
std::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
||||
uint256& out_ephemeralKey,
|
||||
const Ed25519VerificationKey& joinSplitPubKey,
|
||||
const ed25519::VerificationKey& joinSplitPubKey,
|
||||
uint256& out_randomSeed,
|
||||
std::array<uint256, NumInputs>& out_macs,
|
||||
std::array<uint256, NumInputs>& out_nullifiers,
|
||||
|
@ -204,7 +204,7 @@ template<size_t NumInputs, size_t NumOutputs>
|
|||
uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
|
||||
const uint256& randomSeed,
|
||||
const std::array<uint256, NumInputs>& nullifiers,
|
||||
const Ed25519VerificationKey& joinSplitPubKey
|
||||
const ed25519::VerificationKey& joinSplitPubKey
|
||||
) {
|
||||
const unsigned char personalization[blake2b::PERSONALBYTES]
|
||||
= {'Z','c','a','s','h','C','o','m','p','u','t','e','h','S','i','g'};
|
||||
|
@ -215,7 +215,7 @@ uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
|
|||
block.insert(block.end(), nullifiers[i].begin(), nullifiers[i].end());
|
||||
}
|
||||
|
||||
block.insert(block.end(), joinSplitPubKey.bytes, joinSplitPubKey.bytes + ED25519_VERIFICATION_KEY_LEN);
|
||||
block.insert(block.end(), joinSplitPubKey.bytes.begin(), joinSplitPubKey.bytes.end());
|
||||
|
||||
uint256 output;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include <array>
|
||||
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
|
@ -50,7 +50,7 @@ class JoinSplit {
|
|||
public:
|
||||
static uint256 h_sig(const uint256& randomSeed,
|
||||
const std::array<uint256, NumInputs>& nullifiers,
|
||||
const Ed25519VerificationKey& joinSplitPubKey
|
||||
const ed25519::VerificationKey& joinSplitPubKey
|
||||
);
|
||||
|
||||
// Compute nullifiers, macs, note commitments & encryptions, and SNARK proof
|
||||
|
@ -60,7 +60,7 @@ public:
|
|||
std::array<SproutNote, NumOutputs>& out_notes,
|
||||
std::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
||||
uint256& out_ephemeralKey,
|
||||
const Ed25519VerificationKey& joinSplitPubKey,
|
||||
const ed25519::VerificationKey& joinSplitPubKey,
|
||||
uint256& out_randomSeed,
|
||||
std::array<uint256, NumInputs>& out_hmacs,
|
||||
std::array<uint256, NumInputs>& out_nullifiers,
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "librustzcash.h"
|
||||
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/ed25519.h>
|
||||
|
||||
using namespace libzcash;
|
||||
// This method is based on Shutdown from init.cpp
|
||||
|
@ -98,7 +98,7 @@ double benchmark_sleep()
|
|||
|
||||
double benchmark_create_joinsplit()
|
||||
{
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
|
||||
/* Get the anchor of an empty commitment tree. */
|
||||
uint256 anchor = SproutMerkleTree().root();
|
||||
|
@ -145,7 +145,7 @@ double benchmark_verify_joinsplit(const JSDescription &joinsplit)
|
|||
{
|
||||
struct timeval tv_start;
|
||||
timer_start(tv_start);
|
||||
Ed25519VerificationKey joinSplitPubKey;
|
||||
ed25519::VerificationKey joinSplitPubKey;
|
||||
auto verifier = ProofVerifier::Strict();
|
||||
verifier.VerifySprout(joinsplit, joinSplitPubKey);
|
||||
return timer_stop(tv_start);
|
||||
|
|
Loading…
Reference in New Issue