Merge pull request #5357 from nuttycom/feature/wallet_orchard-add_key_types
Add Orchard Address, IncomingViewingKey, and FullViewingKey types.
This commit is contained in:
commit
aa808eb07d
|
@ -521,7 +521,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
|
|||
[[package]]
|
||||
name = "equihash"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
|
@ -530,7 +530,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "f4jumble"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
]
|
||||
|
@ -1112,7 +1112,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|||
[[package]]
|
||||
name = "orchard"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/orchard.git?rev=2c8241f25b943aa05203eacf9905db117c69bd29#2c8241f25b943aa05203eacf9905db117c69bd29"
|
||||
source = "git+https://github.com/zcash/orchard.git?rev=68b790c7dadade049f44ad4aafa0ff71a3a10e91#68b790c7dadade049f44ad4aafa0ff71a3a10e91"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"arrayvec 0.7.2",
|
||||
|
@ -1404,8 +1404,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "reddsa"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/str4d/redjubjub.git?rev=416a6a8ebf8bd42c114c938883016c04f338de72#416a6a8ebf8bd42c114c938883016c04f338de72"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a90e2c94bca3445cae0d55dff7370e29c24885d2403a1665ce19c106c79455e6"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
|
@ -1884,7 +1885,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_address"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
dependencies = [
|
||||
"bech32",
|
||||
"blake2b_simd",
|
||||
|
@ -1896,7 +1897,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_encoding"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"nonempty",
|
||||
|
@ -1905,7 +1906,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_history"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
dependencies = [
|
||||
"bigint",
|
||||
"blake2b_simd",
|
||||
|
@ -1915,7 +1916,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_note_encryption"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
|
@ -1930,7 +1931,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_primitives"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bip0039",
|
||||
|
@ -1964,7 +1965,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_proofs"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=0ec7f97c976d55e1a194a37b27f247e8887fca1d#0ec7f97c976d55e1a194a37b27f247e8887fca1d"
|
||||
dependencies = [
|
||||
"bellman",
|
||||
"blake2b_simd",
|
||||
|
|
12
Cargo.toml
12
Cargo.toml
|
@ -72,9 +72,9 @@ codegen-units = 1
|
|||
[patch.crates-io]
|
||||
ed25519-zebra = { git = "https://github.com/ZcashFoundation/ed25519-zebra.git", rev = "d3512400227a362d08367088ffaa9bd4142a69c7" }
|
||||
incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "b7bd6246122a6e9ace8edb51553fbf5228906cbb" }
|
||||
orchard = { git = "https://github.com/zcash/orchard.git", rev = "2c8241f25b943aa05203eacf9905db117c69bd29" }
|
||||
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }
|
||||
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }
|
||||
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }
|
||||
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }
|
||||
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }
|
||||
orchard = { git = "https://github.com/zcash/orchard.git", rev = "68b790c7dadade049f44ad4aafa0ff71a3a10e91" }
|
||||
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "0ec7f97c976d55e1a194a37b27f247e8887fca1d" }
|
||||
|
|
|
@ -109,6 +109,7 @@ LIBZCASH_H = \
|
|||
zcash/Address.hpp \
|
||||
zcash/address/sapling.hpp \
|
||||
zcash/address/sprout.hpp \
|
||||
zcash/address/orchard.h \
|
||||
zcash/address/zip32.h \
|
||||
zcash/History.hpp \
|
||||
zcash/JoinSplit.hpp \
|
||||
|
@ -537,6 +538,7 @@ libzcash_a_SOURCES = \
|
|||
zcash/Address.cpp \
|
||||
zcash/address/sapling.cpp \
|
||||
zcash/address/sprout.cpp \
|
||||
zcash/address/orchard.cpp \
|
||||
zcash/address/zip32.cpp \
|
||||
zcash/History.cpp \
|
||||
zcash/JoinSplit.cpp \
|
||||
|
|
|
@ -21,7 +21,8 @@ zcash_gtest_SOURCES = \
|
|||
# depend on global state (see #1539)
|
||||
if ENABLE_WALLET
|
||||
zcash_gtest_SOURCES += \
|
||||
wallet/gtest/test_wallet_zkeys.cpp
|
||||
wallet/gtest/test_wallet_zkeys.cpp \
|
||||
wallet/gtest/test_orchard_zkeys.cpp
|
||||
endif
|
||||
zcash_gtest_SOURCES += \
|
||||
test/data/merkle_roots_orchard.h \
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright (c) 2021 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_ORCHARD_KEYS_H
|
||||
#define ZCASH_RUST_INCLUDE_RUST_ORCHARD_KEYS_H
|
||||
|
||||
#include "rust/streams.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A pointer to an Orchard shielded payment address, as defined in
|
||||
* https://zips.z.cash/protocol/nu5.pdf#orchardpaymentaddrencoding
|
||||
*/
|
||||
struct OrchardRawAddressPtr;
|
||||
typedef struct OrchardRawAddressPtr OrchardRawAddressPtr;
|
||||
|
||||
/**
|
||||
* Clones the given Orchard payment address and returns
|
||||
* a pointer to the newly created value. Both the original
|
||||
* one's memory and the newly allocated one need to be freed
|
||||
* independently.
|
||||
*/
|
||||
OrchardRawAddressPtr* orchard_address_clone(
|
||||
const OrchardRawAddressPtr* ptr);
|
||||
|
||||
/**
|
||||
* Frees the memory allocated for the given Orchard payment address
|
||||
*/
|
||||
void orchard_address_free(OrchardRawAddressPtr* ptr);
|
||||
|
||||
//
|
||||
// Incoming Viewing Keys
|
||||
//
|
||||
|
||||
struct OrchardIncomingViewingKeyPtr;
|
||||
typedef struct OrchardIncomingViewingKeyPtr OrchardIncomingViewingKeyPtr;
|
||||
|
||||
/**
|
||||
* Clones the given Orchard incoming viewing key and returns
|
||||
* a pointer to the newly created value. Both the original
|
||||
* one's memory and the newly allocated one need to be freed
|
||||
* independently.
|
||||
*/
|
||||
OrchardIncomingViewingKeyPtr* orchard_incoming_viewing_key_clone(
|
||||
const OrchardIncomingViewingKeyPtr* ptr);
|
||||
|
||||
/**
|
||||
* Frees the memory allocated for the given Orchard incoming viewing key
|
||||
*/
|
||||
void orchard_incoming_viewing_key_free(OrchardIncomingViewingKeyPtr* ptr);
|
||||
|
||||
/**
|
||||
* Returns the address at the specified diversifier index.
|
||||
*/
|
||||
OrchardRawAddressPtr* orchard_incoming_viewing_key_to_address(
|
||||
const OrchardIncomingViewingKeyPtr* incoming_viewing_key,
|
||||
const unsigned char* j);
|
||||
|
||||
/**
|
||||
* Parses an Orchard incoming viewing key from the given stream.
|
||||
*
|
||||
* - If the key does not parse correctly, the returned pointer will be null.
|
||||
*/
|
||||
OrchardIncomingViewingKeyPtr* orchard_incoming_viewing_key_parse(
|
||||
void* stream,
|
||||
read_callback_t read_cb);
|
||||
|
||||
/**
|
||||
* Serializes an Orchard incoming viewing key to the given stream.
|
||||
*/
|
||||
bool orchard_incoming_viewing_key_serialize(
|
||||
const OrchardIncomingViewingKeyPtr* incoming_viewing_key,
|
||||
void* stream,
|
||||
write_callback_t write_cb);
|
||||
|
||||
/**
|
||||
* Implements the "less than" operation for comparing two keys.
|
||||
*/
|
||||
bool orchard_incoming_viewing_key_lt(
|
||||
const OrchardIncomingViewingKeyPtr* k0,
|
||||
const OrchardIncomingViewingKeyPtr* k1);
|
||||
|
||||
/**
|
||||
* Implements equality testing between incoming viewing keys.
|
||||
*/
|
||||
bool orchard_incoming_viewing_key_eq(
|
||||
const OrchardIncomingViewingKeyPtr* k0,
|
||||
const OrchardIncomingViewingKeyPtr* k1);
|
||||
|
||||
//
|
||||
// Full Viewing Keys
|
||||
//
|
||||
|
||||
struct OrchardFullViewingKeyPtr;
|
||||
typedef struct OrchardFullViewingKeyPtr OrchardFullViewingKeyPtr;
|
||||
|
||||
/**
|
||||
* Clones the given Orchard full viewing key and returns
|
||||
* a pointer to the newly created value. Both the original
|
||||
* one's memory and the newly allocated one need to be freed
|
||||
* independently.
|
||||
*/
|
||||
OrchardFullViewingKeyPtr* orchard_full_viewing_key_clone(
|
||||
const OrchardFullViewingKeyPtr* ptr);
|
||||
|
||||
/**
|
||||
* Free the memory allocated for the given Orchard full viewing key
|
||||
*/
|
||||
void orchard_full_viewing_key_free(OrchardFullViewingKeyPtr* ptr);
|
||||
|
||||
/**
|
||||
* Parses an Orchard full viewing key from the given stream.
|
||||
*
|
||||
* - If the key does not parse correctly, the returned pointer will be null.
|
||||
*/
|
||||
OrchardFullViewingKeyPtr* orchard_full_viewing_key_parse(
|
||||
void* stream,
|
||||
read_callback_t read_cb);
|
||||
|
||||
/**
|
||||
* Serializes an Orchard full viewing key to the given stream.
|
||||
*/
|
||||
bool orchard_full_viewing_key_serialize(
|
||||
const OrchardFullViewingKeyPtr* full_viewing_key,
|
||||
void* stream,
|
||||
write_callback_t write_cb);
|
||||
|
||||
/**
|
||||
* Returns the incoming viewing key for the specified full viewing key.
|
||||
*/
|
||||
OrchardIncomingViewingKeyPtr* orchard_full_viewing_key_to_incoming_viewing_key(
|
||||
const OrchardFullViewingKeyPtr* key);
|
||||
|
||||
/**
|
||||
* Implements equality testing between full viewing keys.
|
||||
*/
|
||||
bool orchard_full_viewing_key_eq(
|
||||
const OrchardFullViewingKeyPtr* k0,
|
||||
const OrchardFullViewingKeyPtr* k1);
|
||||
|
||||
//
|
||||
// Spending Keys
|
||||
//
|
||||
|
||||
struct OrchardSpendingKeyPtr;
|
||||
typedef struct OrchardSpendingKeyPtr OrchardSpendingKeyPtr;
|
||||
|
||||
/**
|
||||
* Constructs a spending key by ZIP-32 derivation to the account
|
||||
* level from the provided seed.
|
||||
*/
|
||||
OrchardSpendingKeyPtr* orchard_spending_key_for_account(
|
||||
const unsigned char* seed,
|
||||
size_t seed_len,
|
||||
uint32_t bip44_coin_type,
|
||||
uint32_t account_id);
|
||||
|
||||
/**
|
||||
* Clones the given Orchard spending key and returns
|
||||
* a pointer to the newly created value. Both the original
|
||||
* one's memory and the newly allocated one need to be freed
|
||||
* independently.
|
||||
*/
|
||||
OrchardSpendingKeyPtr* orchard_spending_key_clone(
|
||||
const OrchardSpendingKeyPtr* ptr);
|
||||
|
||||
/**
|
||||
* Free the memory allocated for the given Orchard spending key
|
||||
*/
|
||||
void orchard_spending_key_free(OrchardSpendingKeyPtr* ptr);
|
||||
|
||||
/**
|
||||
* Parses an Orchard spending key from the given stream.
|
||||
*
|
||||
* - If the key does not parse correctly, the returned pointer will be null.
|
||||
*/
|
||||
OrchardSpendingKeyPtr* orchard_spending_key_parse(
|
||||
void* stream,
|
||||
read_callback_t read_cb);
|
||||
|
||||
/**
|
||||
* Serializes an Orchard spending key to the given stream.
|
||||
*/
|
||||
bool orchard_spending_key_serialize(
|
||||
const OrchardSpendingKeyPtr* spending_key,
|
||||
void* stream,
|
||||
write_callback_t write_cb);
|
||||
|
||||
/**
|
||||
* Returns the full viewing key for the specified spending key.
|
||||
*/
|
||||
OrchardFullViewingKeyPtr* orchard_spending_key_to_full_viewing_key(
|
||||
const OrchardSpendingKeyPtr* key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZCASH_RUST_INCLUDE_RUST_ORCHARD_KEYS_H
|
|
@ -0,0 +1,287 @@
|
|||
use std::io::{Read, Write};
|
||||
use std::slice;
|
||||
use tracing::error;
|
||||
|
||||
use orchard::keys::{DiversifierIndex, FullViewingKey, IncomingViewingKey, SpendingKey};
|
||||
use orchard::Address;
|
||||
|
||||
use crate::streams_ffi::{CppStreamReader, CppStreamWriter, ReadCb, StreamObj, WriteCb};
|
||||
|
||||
//
|
||||
// Addresses
|
||||
//
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_address_clone(addr: *const Address) -> *mut Address {
|
||||
unsafe { addr.as_ref() }
|
||||
.map(|addr| Box::into_raw(Box::new(*addr)))
|
||||
.unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_address_free(addr: *mut Address) {
|
||||
if !addr.is_null() {
|
||||
drop(unsafe { Box::from_raw(addr) });
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Incoming viewing keys
|
||||
//
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_incoming_viewing_key_clone(
|
||||
key: *const IncomingViewingKey,
|
||||
) -> *mut IncomingViewingKey {
|
||||
unsafe { key.as_ref() }
|
||||
.map(|key| Box::into_raw(Box::new(key.clone())))
|
||||
.unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_incoming_viewing_key_free(key: *mut IncomingViewingKey) {
|
||||
if !key.is_null() {
|
||||
drop(unsafe { Box::from_raw(key) });
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_incoming_viewing_key_parse(
|
||||
stream: Option<StreamObj>,
|
||||
read_cb: Option<ReadCb>,
|
||||
) -> *mut IncomingViewingKey {
|
||||
let mut reader = CppStreamReader::from_raw_parts(stream, read_cb.unwrap());
|
||||
|
||||
let mut buf = [0u8; 64];
|
||||
match reader.read_exact(&mut buf) {
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Stream failure reading bytes of Orchard incoming viewing key: {}",
|
||||
e
|
||||
);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
Ok(()) => {
|
||||
let read = IncomingViewingKey::from_bytes(&buf);
|
||||
if read.is_some().into() {
|
||||
Box::into_raw(Box::new(read.unwrap()))
|
||||
} else {
|
||||
error!("Failed to parse Orchard incoming viewing key.");
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_incoming_viewing_key_to_address(
|
||||
key: *const IncomingViewingKey,
|
||||
diversifier_index: *const [u8; 11],
|
||||
) -> *mut Address {
|
||||
let key =
|
||||
unsafe { key.as_ref() }.expect("Orchard incoming viewing key pointer may not be null.");
|
||||
|
||||
let diversifier_index = DiversifierIndex::from(unsafe { *diversifier_index });
|
||||
Box::into_raw(Box::new(key.address_at(diversifier_index)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_incoming_viewing_key_serialize(
|
||||
key: *const IncomingViewingKey,
|
||||
stream: Option<StreamObj>,
|
||||
write_cb: Option<WriteCb>,
|
||||
) -> bool {
|
||||
let key =
|
||||
unsafe { key.as_ref() }.expect("Orchard incoming viewing key pointer may not be null.");
|
||||
|
||||
let mut writer = CppStreamWriter::from_raw_parts(stream, write_cb.unwrap());
|
||||
match writer.write_all(&key.to_bytes()) {
|
||||
Ok(()) => true,
|
||||
Err(e) => {
|
||||
error!("Stream failure writing Orchard incoming viewing key: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_incoming_viewing_key_lt(
|
||||
k0: *const IncomingViewingKey,
|
||||
k1: *const IncomingViewingKey,
|
||||
) -> bool {
|
||||
let k0 = unsafe { k0.as_ref() };
|
||||
let k1 = unsafe { k1.as_ref() };
|
||||
k0 < k1
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_incoming_viewing_key_eq(
|
||||
k0: *const IncomingViewingKey,
|
||||
k1: *const IncomingViewingKey,
|
||||
) -> bool {
|
||||
let k0 = unsafe { k0.as_ref() };
|
||||
let k1 = unsafe { k1.as_ref() };
|
||||
k0 == k1
|
||||
}
|
||||
|
||||
//
|
||||
// Full viewing keys
|
||||
//
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_full_viewing_key_clone(
|
||||
key: *const FullViewingKey,
|
||||
) -> *mut FullViewingKey {
|
||||
unsafe { key.as_ref() }
|
||||
.map(|key| Box::into_raw(Box::new(key.clone())))
|
||||
.unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_full_viewing_key_free(key: *mut FullViewingKey) {
|
||||
if !key.is_null() {
|
||||
drop(unsafe { Box::from_raw(key) });
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_full_viewing_key_parse(
|
||||
stream: Option<StreamObj>,
|
||||
read_cb: Option<ReadCb>,
|
||||
) -> *mut FullViewingKey {
|
||||
let reader = CppStreamReader::from_raw_parts(stream, read_cb.unwrap());
|
||||
|
||||
match FullViewingKey::read(reader) {
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Stream failure reading bytes of Orchard full viewing key: {}",
|
||||
e
|
||||
);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
Ok(fvk) => Box::into_raw(Box::new(fvk)),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_full_viewing_key_serialize(
|
||||
key: *const FullViewingKey,
|
||||
stream: Option<StreamObj>,
|
||||
write_cb: Option<WriteCb>,
|
||||
) -> bool {
|
||||
let key = unsafe { key.as_ref() }.expect("Orchard full viewing key pointer may not be null.");
|
||||
|
||||
let mut writer = CppStreamWriter::from_raw_parts(stream, write_cb.unwrap());
|
||||
match key.write(&mut writer) {
|
||||
Ok(()) => true,
|
||||
Err(e) => {
|
||||
error!("Stream failure writing Orchard full viewing key: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_full_viewing_key_to_incoming_viewing_key(
|
||||
key: *const FullViewingKey,
|
||||
) -> *mut IncomingViewingKey {
|
||||
unsafe { key.as_ref() }
|
||||
.map(|key| Box::into_raw(Box::new(IncomingViewingKey::from(key))))
|
||||
.unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_full_viewing_key_eq(
|
||||
k0: *const FullViewingKey,
|
||||
k1: *const FullViewingKey,
|
||||
) -> bool {
|
||||
let k0 = unsafe { k0.as_ref() };
|
||||
let k1 = unsafe { k1.as_ref() };
|
||||
k0 == k1
|
||||
}
|
||||
|
||||
//
|
||||
// Spending keys
|
||||
//
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_spending_key_for_account(
|
||||
seed: *const u8,
|
||||
seed_len: usize,
|
||||
bip44_coin_type: u32,
|
||||
account_id: u32,
|
||||
) -> *mut SpendingKey {
|
||||
let seed = unsafe { slice::from_raw_parts(seed, seed_len) };
|
||||
SpendingKey::from_zip32_seed(seed, bip44_coin_type, account_id)
|
||||
.map(|key| Box::into_raw(Box::new(key)))
|
||||
.unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_spending_key_clone(key: *const SpendingKey) -> *mut SpendingKey {
|
||||
unsafe { key.as_ref() }
|
||||
.map(|key| Box::into_raw(Box::new(*key)))
|
||||
.unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_spending_key_free(key: *mut SpendingKey) {
|
||||
if !key.is_null() {
|
||||
drop(unsafe { Box::from_raw(key) });
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_spending_key_parse(
|
||||
stream: Option<StreamObj>,
|
||||
read_cb: Option<ReadCb>,
|
||||
) -> *mut SpendingKey {
|
||||
let mut reader = CppStreamReader::from_raw_parts(stream, read_cb.unwrap());
|
||||
|
||||
let mut buf = [0u8; 32];
|
||||
match reader.read_exact(&mut buf) {
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Stream failure reading bytes of Orchard spending key: {}",
|
||||
e
|
||||
);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
Ok(()) => {
|
||||
let sk_opt = SpendingKey::from_bytes(buf);
|
||||
if sk_opt.is_some().into() {
|
||||
Box::into_raw(Box::new(sk_opt.unwrap()))
|
||||
} else {
|
||||
error!("Failed to parse Orchard spending key.");
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_spending_key_serialize(
|
||||
key: *const SpendingKey,
|
||||
stream: Option<StreamObj>,
|
||||
write_cb: Option<WriteCb>,
|
||||
) -> bool {
|
||||
let key = unsafe { key.as_ref() }.expect("Orchard spending key pointer may not be null.");
|
||||
|
||||
let mut writer = CppStreamWriter::from_raw_parts(stream, write_cb.unwrap());
|
||||
match writer.write_all(key.to_bytes()) {
|
||||
Ok(()) => true,
|
||||
Err(e) => {
|
||||
error!("Stream failure writing Orchard spending key: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn orchard_spending_key_to_full_viewing_key(
|
||||
key: *const SpendingKey,
|
||||
) -> *mut FullViewingKey {
|
||||
unsafe { key.as_ref() }
|
||||
.map(|key| Box::into_raw(Box::new(FullViewingKey::from(key))))
|
||||
.unwrap_or(std::ptr::null_mut())
|
||||
}
|
|
@ -72,6 +72,7 @@ mod address_ffi;
|
|||
mod history_ffi;
|
||||
mod incremental_merkle_tree_ffi;
|
||||
mod orchard_ffi;
|
||||
mod orchard_keys_ffi;
|
||||
mod transaction_ffi;
|
||||
mod zip339_ffi;
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) 2021 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "zcash/address/orchard.hpp"
|
||||
|
||||
TEST(OrchardZkeysTest, IVKSerializationRoundtrip) {
|
||||
auto seed = MnemonicSeed::Random(1); //testnet coin type
|
||||
auto sk = libzcash::OrchardSpendingKey::ForAccount(seed, 1, 0);
|
||||
auto fvk = sk.ToFullViewingKey();
|
||||
auto ivk = fvk.ToIncomingViewingKey();
|
||||
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << ivk;
|
||||
|
||||
auto ivk0 = libzcash::OrchardIncomingViewingKey::Read(ss);
|
||||
|
||||
ASSERT_EQ(ivk, ivk0);
|
||||
}
|
||||
|
||||
TEST(OrchardZkeysTest, FVKSerializationRoundtrip) {
|
||||
auto seed = MnemonicSeed::Random(1); //testnet coin type
|
||||
auto sk = libzcash::OrchardSpendingKey::ForAccount(seed, 1, 0);
|
||||
auto fvk = sk.ToFullViewingKey();
|
||||
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << fvk;
|
||||
|
||||
auto fvk0 = libzcash::OrchardFullViewingKey::Read(ss);
|
||||
|
||||
ASSERT_EQ(fvk, fvk0);
|
||||
}
|
||||
|
||||
TEST(OrchardZkeysTest, SKSerializationRoundtrip) {
|
||||
auto seed = MnemonicSeed::Random(1); //testnet coin type
|
||||
|
||||
auto sk = libzcash::OrchardSpendingKey::ForAccount(seed, 1, 0);
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << sk;
|
||||
std::string skStr = ss.str();
|
||||
|
||||
auto sk0 = libzcash::OrchardSpendingKey::Read(ss);
|
||||
CDataStream ss0(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss0 << sk0;
|
||||
std::string sk0Str = ss0.str();
|
||||
|
||||
ASSERT_EQ(skStr, sk0Str);
|
||||
}
|
|
@ -431,7 +431,7 @@ ZcashdUnifiedSpendingKey CWallet::GenerateNewUnifiedSpendingKey() {
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<libzcash::ZcashdUnifiedSpendingKey> CWallet::GenerateUnifiedSpendingKeyForAccount(uint32_t accountId) {
|
||||
std::optional<libzcash::ZcashdUnifiedSpendingKey> CWallet::GenerateUnifiedSpendingKeyForAccount(libzcash::AccountId accountId) {
|
||||
auto seed = GetMnemonicSeed();
|
||||
if (!seed.has_value()) {
|
||||
throw std::runtime_error(std::string(__func__) + ": Wallet has no mnemonic HD seed.");
|
||||
|
|
|
@ -1097,7 +1097,7 @@ public:
|
|||
* Unified keys & addresses
|
||||
*/
|
||||
libzcash::ZcashdUnifiedSpendingKey GenerateNewUnifiedSpendingKey();
|
||||
std::optional<libzcash::ZcashdUnifiedSpendingKey> GenerateUnifiedSpendingKeyForAccount(uint32_t accountId);
|
||||
std::optional<libzcash::ZcashdUnifiedSpendingKey> GenerateUnifiedSpendingKeyForAccount(libzcash::AccountId accountId);
|
||||
|
||||
/**
|
||||
* Increment the next transaction order id
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define ZC_ADDRESS_H_
|
||||
|
||||
#include "uint256.h"
|
||||
#include "zcash/address/orchard.hpp"
|
||||
#include "zcash/address/sapling.hpp"
|
||||
#include "zcash/address/sprout.hpp"
|
||||
#include "zcash/address/zip32.h"
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) 2021 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#include "zcash/address/orchard.hpp"
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
OrchardRawAddress OrchardIncomingViewingKey::Address(const diversifier_index_t& j) const {
|
||||
return OrchardRawAddress(orchard_incoming_viewing_key_to_address(inner.get(), j.begin()));
|
||||
}
|
||||
|
||||
OrchardIncomingViewingKey OrchardFullViewingKey::ToIncomingViewingKey() const {
|
||||
return OrchardIncomingViewingKey(orchard_full_viewing_key_to_incoming_viewing_key(inner.get()));
|
||||
}
|
||||
|
||||
OrchardSpendingKey OrchardSpendingKey::ForAccount(
|
||||
const HDSeed& seed,
|
||||
uint32_t bip44CoinType,
|
||||
libzcash::AccountId accountId) {
|
||||
|
||||
auto ptr = orchard_spending_key_for_account(
|
||||
seed.RawSeed().data(),
|
||||
seed.RawSeed().size(),
|
||||
bip44CoinType,
|
||||
accountId);
|
||||
|
||||
if (ptr == nullptr) {
|
||||
throw std::ios_base::failure("Unable to generate Orchard extended spending key.");
|
||||
}
|
||||
|
||||
return OrchardSpendingKey(ptr);
|
||||
}
|
||||
|
||||
OrchardFullViewingKey OrchardSpendingKey::ToFullViewingKey() const {
|
||||
return OrchardFullViewingKey(orchard_spending_key_to_full_viewing_key(inner.get()));
|
||||
}
|
||||
|
||||
} //namespace libzcash
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
// Copyright (c) 2021 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_ADDRESS_ORCHARD_H
|
||||
#define ZCASH_ADDRESS_ORCHARD_H
|
||||
|
||||
#include "streams.h"
|
||||
#include "zcash/address/zip32.h"
|
||||
#include <rust/orchard/keys.h>
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
class OrchardIncomingViewingKey;
|
||||
|
||||
class OrchardRawAddress
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<OrchardRawAddressPtr, decltype(&orchard_address_free)> inner;
|
||||
|
||||
OrchardRawAddress() : inner(nullptr, orchard_address_free) {}
|
||||
|
||||
OrchardRawAddress(OrchardRawAddressPtr* ptr) : inner(ptr, orchard_address_free) {}
|
||||
|
||||
friend class OrchardIncomingViewingKey;
|
||||
public:
|
||||
OrchardRawAddress(OrchardRawAddress&& key) : inner(std::move(key.inner)) {}
|
||||
|
||||
OrchardRawAddress(const OrchardRawAddress& key) :
|
||||
inner(orchard_address_clone(key.inner.get()), orchard_address_free) {}
|
||||
|
||||
OrchardRawAddress& operator=(OrchardRawAddress&& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner = std::move(key.inner);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OrchardRawAddress& operator=(const OrchardRawAddress& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner.reset(orchard_address_clone(key.inner.get()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class OrchardFullViewingKey;
|
||||
|
||||
class OrchardIncomingViewingKey
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<OrchardIncomingViewingKeyPtr, decltype(&orchard_incoming_viewing_key_free)> inner;
|
||||
|
||||
OrchardIncomingViewingKey() : inner(nullptr, orchard_incoming_viewing_key_free) {}
|
||||
|
||||
OrchardIncomingViewingKey(OrchardIncomingViewingKeyPtr* key) :
|
||||
inner(key, orchard_incoming_viewing_key_free) {}
|
||||
|
||||
friend class OrchardFullViewingKey;
|
||||
public:
|
||||
|
||||
OrchardIncomingViewingKey(OrchardIncomingViewingKey&& key) : inner(std::move(key.inner)) {}
|
||||
|
||||
OrchardIncomingViewingKey(const OrchardIncomingViewingKey& key) :
|
||||
inner(orchard_incoming_viewing_key_clone(key.inner.get()), orchard_incoming_viewing_key_free) {}
|
||||
|
||||
OrchardRawAddress Address(const diversifier_index_t& j) const;
|
||||
|
||||
OrchardIncomingViewingKey& operator=(OrchardIncomingViewingKey&& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner = std::move(key.inner);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OrchardIncomingViewingKey& operator=(const OrchardIncomingViewingKey& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner.reset(orchard_incoming_viewing_key_clone(key.inner.get()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const OrchardIncomingViewingKey& a, const OrchardIncomingViewingKey& b)
|
||||
{
|
||||
return orchard_incoming_viewing_key_eq(a.inner.get(), b.inner.get());
|
||||
}
|
||||
|
||||
friend bool operator<(const OrchardIncomingViewingKey& c1, const OrchardIncomingViewingKey& c2) {
|
||||
return orchard_incoming_viewing_key_lt(c1.inner.get(), c2.inner.get());
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const {
|
||||
RustStream rs(s);
|
||||
if (!orchard_incoming_viewing_key_serialize(inner.get(), &rs, RustStream<Stream>::write_callback)) {
|
||||
throw std::ios_base::failure("Failed to serialize Orchard incoming viewing key");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s) {
|
||||
RustStream rs(s);
|
||||
OrchardIncomingViewingKeyPtr* key = orchard_incoming_viewing_key_parse(&rs, RustStream<Stream>::read_callback);
|
||||
if (key == nullptr) {
|
||||
throw std::ios_base::failure("Failed to parse Orchard incoming viewing key");
|
||||
}
|
||||
inner.reset(key);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
static OrchardIncomingViewingKey Read(Stream& stream) {
|
||||
OrchardIncomingViewingKey key;
|
||||
stream >> key;
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
class OrchardSpendingKey;
|
||||
|
||||
class OrchardFullViewingKey
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<OrchardFullViewingKeyPtr, decltype(&orchard_full_viewing_key_free)> inner;
|
||||
|
||||
OrchardFullViewingKey() : inner(nullptr, orchard_full_viewing_key_free) {}
|
||||
|
||||
OrchardFullViewingKey(OrchardFullViewingKeyPtr* ptr) :
|
||||
inner(ptr, orchard_full_viewing_key_free) {}
|
||||
|
||||
friend class OrchardSpendingKey;
|
||||
public:
|
||||
OrchardFullViewingKey(OrchardFullViewingKey&& key) : inner(std::move(key.inner)) {}
|
||||
|
||||
OrchardFullViewingKey(const OrchardFullViewingKey& key) :
|
||||
inner(orchard_full_viewing_key_clone(key.inner.get()), orchard_full_viewing_key_free) {}
|
||||
|
||||
OrchardFullViewingKey& operator=(OrchardFullViewingKey&& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner = std::move(key.inner);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OrchardFullViewingKey& operator=(const OrchardFullViewingKey& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner.reset(orchard_full_viewing_key_clone(key.inner.get()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const OrchardFullViewingKey& a, const OrchardFullViewingKey& b)
|
||||
{
|
||||
return orchard_full_viewing_key_eq(a.inner.get(), b.inner.get());
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const {
|
||||
RustStream rs(s);
|
||||
if (!orchard_full_viewing_key_serialize(inner.get(), &rs, RustStream<Stream>::write_callback)) {
|
||||
throw std::ios_base::failure("Failed to serialize Orchard full viewing key");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s) {
|
||||
RustStream rs(s);
|
||||
OrchardFullViewingKeyPtr* key = orchard_full_viewing_key_parse(&rs, RustStream<Stream>::read_callback);
|
||||
if (key == nullptr) {
|
||||
throw std::ios_base::failure("Failed to parse Orchard full viewing key");
|
||||
}
|
||||
inner.reset(key);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
static OrchardFullViewingKey Read(Stream& stream) {
|
||||
OrchardFullViewingKey key;
|
||||
stream >> key;
|
||||
return key;
|
||||
}
|
||||
|
||||
OrchardIncomingViewingKey ToIncomingViewingKey() const;
|
||||
};
|
||||
|
||||
class OrchardSpendingKey
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<OrchardSpendingKeyPtr, decltype(&orchard_spending_key_free)> inner;
|
||||
|
||||
OrchardSpendingKey() : inner(nullptr, orchard_spending_key_free) {}
|
||||
|
||||
OrchardSpendingKey(OrchardSpendingKeyPtr* ptr) :
|
||||
inner(ptr, orchard_spending_key_free) {}
|
||||
public:
|
||||
OrchardSpendingKey(OrchardSpendingKey&& key) : inner(std::move(key.inner)) {}
|
||||
|
||||
OrchardSpendingKey(const OrchardSpendingKey& key) :
|
||||
inner(orchard_spending_key_clone(key.inner.get()), orchard_spending_key_free) {}
|
||||
|
||||
static OrchardSpendingKey ForAccount(
|
||||
const HDSeed& seed,
|
||||
uint32_t bip44CoinType,
|
||||
libzcash::AccountId accountId);
|
||||
|
||||
OrchardSpendingKey& operator=(OrchardSpendingKey&& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner = std::move(key.inner);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OrchardSpendingKey& operator=(const OrchardSpendingKey& key)
|
||||
{
|
||||
if (this != &key) {
|
||||
inner.reset(orchard_spending_key_clone(key.inner.get()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const {
|
||||
RustStream rs(s);
|
||||
if (!orchard_spending_key_serialize(inner.get(), &rs, RustStream<Stream>::write_callback)) {
|
||||
throw std::ios_base::failure("Failed to serialize Orchard spending key");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s) {
|
||||
RustStream rs(s);
|
||||
OrchardSpendingKeyPtr* key = orchard_spending_key_parse(&rs, RustStream<Stream>::read_callback);
|
||||
if (key == nullptr) {
|
||||
throw std::ios_base::failure("Failed to parse Orchard spending key");
|
||||
}
|
||||
inner.reset(key);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
static OrchardSpendingKey Read(Stream& stream) {
|
||||
OrchardSpendingKey key;
|
||||
stream >> key;
|
||||
return key;
|
||||
}
|
||||
|
||||
OrchardFullViewingKey ToFullViewingKey() const;
|
||||
};
|
||||
|
||||
} // namespace libzcash
|
||||
|
||||
#endif // ZCASH_ADDRESS_ORCHARD_H
|
||||
|
|
@ -85,7 +85,7 @@ std::optional<unsigned int> diversifier_index_t::ToTransparentChildIndex() const
|
|||
// Transparent
|
||||
//
|
||||
|
||||
std::optional<std::pair<CExtKey, HDKeyPath>> DeriveBip44TransparentAccountKey(const MnemonicSeed& seed, uint32_t bip44CoinType, uint32_t accountId) {
|
||||
std::optional<std::pair<CExtKey, HDKeyPath>> DeriveBip44TransparentAccountKey(const MnemonicSeed& seed, uint32_t bip44CoinType, libzcash::AccountId accountId) {
|
||||
auto rawSeed = seed.RawSeed();
|
||||
auto m = CExtKey::Master(rawSeed.data(), rawSeed.size());
|
||||
|
||||
|
@ -110,7 +110,7 @@ std::optional<std::pair<CExtKey, HDKeyPath>> DeriveBip44TransparentAccountKey(co
|
|||
std::optional<Bip44AccountChains> Bip44AccountChains::ForAccount(
|
||||
const MnemonicSeed& seed,
|
||||
uint32_t bip44CoinType,
|
||||
uint32_t accountId) {
|
||||
libzcash::AccountId accountId) {
|
||||
auto accountKeyOpt = DeriveBip44TransparentAccountKey(seed, bip44CoinType, accountId);
|
||||
if (!accountKeyOpt.has_value()) return std::nullopt;
|
||||
|
||||
|
@ -251,7 +251,7 @@ SaplingExtendedSpendingKey SaplingExtendedSpendingKey::Derive(uint32_t i) const
|
|||
return xsk_i;
|
||||
}
|
||||
|
||||
std::pair<SaplingExtendedSpendingKey, HDKeyPath> SaplingExtendedSpendingKey::ForAccount(const MnemonicSeed& seed, uint32_t bip44CoinType, uint32_t accountId) {
|
||||
std::pair<SaplingExtendedSpendingKey, HDKeyPath> SaplingExtendedSpendingKey::ForAccount(const MnemonicSeed& seed, uint32_t bip44CoinType, libzcash::AccountId accountId) {
|
||||
auto m = Master(seed);
|
||||
|
||||
// We use a fixed keypath scheme of m/32'/coin_type'/account'
|
||||
|
@ -313,7 +313,7 @@ SaplingExtendedFullViewingKey SaplingExtendedSpendingKey::ToXFVK() const
|
|||
// Unified
|
||||
//
|
||||
|
||||
std::optional<std::pair<ZcashdUnifiedSpendingKey, HDKeyPath>> ZcashdUnifiedSpendingKey::ForAccount(const MnemonicSeed& seed, uint32_t bip44CoinType, uint32_t accountId) {
|
||||
std::optional<std::pair<ZcashdUnifiedSpendingKey, HDKeyPath>> ZcashdUnifiedSpendingKey::ForAccount(const MnemonicSeed& seed, uint32_t bip44CoinType, libzcash::AccountId accountId) {
|
||||
ZcashdUnifiedSpendingKey usk;
|
||||
usk.accountId = accountId;
|
||||
|
||||
|
|
|
@ -165,6 +165,8 @@ uint256 ovkForShieldingFromTaddr(HDSeed& seed);
|
|||
|
||||
namespace libzcash {
|
||||
|
||||
typedef uint32_t AccountId;
|
||||
|
||||
/**
|
||||
* 88-bit diversifier index. This would ideally derive from base_uint
|
||||
* but those values must have bit widths that are multiples of 32.
|
||||
|
@ -290,7 +292,7 @@ struct SaplingExtendedSpendingKey {
|
|||
}
|
||||
|
||||
static SaplingExtendedSpendingKey Master(const HDSeed& seed);
|
||||
static std::pair<SaplingExtendedSpendingKey, HDKeyPath> ForAccount(const MnemonicSeed& seed, uint32_t bip44CoinType, uint32_t accountId);
|
||||
static std::pair<SaplingExtendedSpendingKey, HDKeyPath> ForAccount(const MnemonicSeed& seed, uint32_t bip44CoinType, libzcash::AccountId accountId);
|
||||
static std::pair<SaplingExtendedSpendingKey, HDKeyPath> Legacy(const MnemonicSeed& seed, uint32_t bip44CoinType, uint32_t addressIndex);
|
||||
|
||||
|
||||
|
@ -363,7 +365,7 @@ public:
|
|||
|
||||
class ZcashdUnifiedSpendingKey {
|
||||
private:
|
||||
uint32_t accountId;
|
||||
libzcash::AccountId accountId;
|
||||
std::optional<CExtKey> transparentKey;
|
||||
std::optional<SaplingExtendedSpendingKey> saplingKey;
|
||||
|
||||
|
@ -372,7 +374,7 @@ public:
|
|||
static std::optional<std::pair<ZcashdUnifiedSpendingKey, HDKeyPath>> ForAccount(
|
||||
const MnemonicSeed& mnemonic,
|
||||
uint32_t bip44CoinType,
|
||||
uint32_t accountId);
|
||||
libzcash::AccountId accountId);
|
||||
|
||||
const std::optional<CExtKey>& GetTransparentKey() const {
|
||||
return transparentKey;
|
||||
|
@ -390,18 +392,18 @@ std::optional<unsigned long> ParseHDKeypathAccount(uint32_t purpose, uint32_t co
|
|||
class Bip44AccountChains {
|
||||
private:
|
||||
uint256 seedFp;
|
||||
uint32_t accountId;
|
||||
libzcash::AccountId accountId;
|
||||
uint32_t bip44CoinType;
|
||||
CExtKey external;
|
||||
CExtKey internal;
|
||||
|
||||
Bip44AccountChains(uint256 seedFpIn, uint32_t bip44CoinTypeIn, uint32_t accountIdIn, CExtKey externalIn, CExtKey internalIn):
|
||||
Bip44AccountChains(uint256 seedFpIn, uint32_t bip44CoinTypeIn, libzcash::AccountId accountIdIn, CExtKey externalIn, CExtKey internalIn):
|
||||
seedFp(seedFpIn), accountId(accountIdIn), bip44CoinType(bip44CoinTypeIn), external(externalIn), internal(internalIn) {}
|
||||
public:
|
||||
static std::optional<Bip44AccountChains> ForAccount(
|
||||
const MnemonicSeed& mnemonic,
|
||||
uint32_t bip44CoinType,
|
||||
uint32_t accountId);
|
||||
libzcash::AccountId accountId);
|
||||
|
||||
std::optional<std::pair<CExtKey, HDKeyPath>> DeriveExternal(uint32_t addrIndex);
|
||||
std::optional<std::pair<CExtKey, HDKeyPath>> DeriveInternal(uint32_t addrIndex);
|
||||
|
|
Loading…
Reference in New Issue