profile
viewpoint

jdegoes/blueeyes 731

A lightweight Web 3.0 framework for Scala, featuring a purely asynchronous architecture, extremely high-performance, massive scalability, high usability, and a functional, composable design.

fponticelli/thx.core 109

Super-charged standard library for Haxe.

fponticelli/thx.format 20

Formatting library for Haxe.

jdegoes/RosettaJson 14

A Scala library for library authors who want to support different JSON libraries.

nuttycom/commons-pipeline 11

The github home of the Apache commons-pipeline project, a project that I originated in 2004.

nuttycom/colorlife-games 5

A platform for competetive variants of Conway's Game of Life written in Scala

aftok/bippy 2

Haskell library for creation of BIP-70 Payment Protocol payment request data.

hylotech/suits 2

Miscellaneous Scala utility classes.

issue commentzcash/zips

[ZIP 315] Best Practices for Wallet Handling of Multiple Pools

Initial draft notes: https://hackmd.io/P-yE8MYWSVygt0OznYhL7g?view

daira

comment created time in 16 hours

Pull request review commentzcash/zcash

Implement wallet UA RPCs

 UniValue z_getaddressforaccount(const UniValue& params, bool fHelp)     if (!fExperimentalOrchardWallet) {         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: the Orchard wallet experimental extensions are disabled.");     }-    int64_t account = params[0].get_int64();-    if (account < 0 || account >= ZCASH_LEGACY_ACCOUNT) {++    LOCK(pwalletMain->cs_wallet);++    int64_t accountInt = params[0].get_int64();+    if (accountInt < 0 || accountInt >= ZCASH_LEGACY_ACCOUNT) {         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid account number, must be 0 <= account <= (2^31)-2.");     }-    // TODO: Check that the account is known to the wallet.-    std::vector<uint8_t> parsed_diversifier_index;+    libzcash::AccountId account = accountInt;++    std::optional<libzcash::diversifier_index_t> j = std::nullopt;     if (params.size() >= 2) {+        // TODO: Handle '*'         if (params[1].getType() != UniValue::VNUM) {             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid diversifier index, must be an unsigned integer.");         }         auto parsed_diversifier_index_opt = ParseArbitraryInt(params[1].getValStr());         if (!parsed_diversifier_index_opt.has_value()) {             throw JSONRPCError(RPC_INVALID_PARAMETER, "diversifier index must be a decimal integer.");         }-        parsed_diversifier_index = parsed_diversifier_index_opt.value();+        auto parsed_diversifier_index = parsed_diversifier_index_opt.value();         if (parsed_diversifier_index.size() > ZC_DIVERSIFIER_SIZE) {             throw JSONRPCError(RPC_INVALID_PARAMETER, "diversifier index is too large.");         }-    } else {-        // TODO get next unused diversifier index from wallet+        j = libzcash::diversifier_index_t(parsed_diversifier_index);     }-    // TODO:-    // diversifier_t diversifier{};-    // std::copy(parsed_diversifier_index.begin(), parsed_diversifier_index.end(), diversifier.begin());-    UniValue pools(UniValue::VARR);++    std::set<libzcash::ReceiverType> receivers;     if (params.size() >= 3) {-        pools = params[2].get_array();+        const auto& pools = params[2].get_array();         for (unsigned int i = 0; i < pools.size(); i++) {             const std::string& p = pools[i].get_str();-            if (!(p == "transparent" || p == "sapling" || p == "orchard")) {-                throw JSONRPCError(RPC_INVALID_PARAMETER, "pool arguments must be \"transparent\", \"sapling\", or \"orchard\"");+            if (p == "transparent") {+                receivers.insert(ReceiverType::P2PKH);+            } else if (p == "sapling") {+                receivers.insert(ReceiverType::Sapling);+            } else {+                throw JSONRPCError(RPC_INVALID_PARAMETER, "pool arguments must be \"transparent\", or \"sapling\"");             }         }     } else {-        // default is all-        pools.push_back("transparent");-        pools.push_back("sapling");-        pools.push_back("orchard");+        // Default is the best and second-best shielded pools, and the transparent pool.+        receivers = {ReceiverType::P2PKH, ReceiverType::Sapling};     }++    EnsureWalletIsUnlocked();++    // Generate the first UA for this account, using the best and next-best shielded pools+    // and the transparent pool.+    auto res = pwalletMain->GenerateUnifiedAddress(account, receivers, j);+     UniValue result(UniValue::VOBJ);-    result.pushKV("account", account);-    result.pushKV("diversifier_index", params[1].write());+    result.pushKV("account", (uint64_t)account);++    std::visit(match {+        [&](std::pair<libzcash::UnifiedAddress, libzcash::diversifier_index_t> addr) {+            result.pushKV("unifiedaddress", KeyIO(Params()).EncodePaymentAddress(addr.first));+            result.pushKV("diversifier_index", ArbitraryIntStr(std::vector(addr.second.begin(), addr.second.end())));+        },+        [&](AddressGenerationError err) {+            std::string strErr;+            switch (err) {+                case AddressGenerationError::NoSuchAccount:+                    strErr = tfm::format("Error: account %d has not been generated by z_getnewaccount.", account);+                    break;+                case AddressGenerationError::ExistingAddressMismatch:+                    strErr = tfm::format(+                        "Error: address at diversifier index %s was already generated with different receiver types.",+                        params[1].getValStr());+                    break;+                case AddressGenerationError::NoAddressForDiversifier:+                    strErr = tfm::format(+                        "Error: no address at diversifier index %s was already generated with different receiver types.",+                        ArbitraryIntStr(std::vector(j.value().begin(), j.value().end())));+                    break;+                case AddressGenerationError::InvalidTransparentChildIndex:+                    strErr = tfm::format(+                        "Error: diversifier index %s cannot generate an address with a transparent receiver.",+                        ArbitraryIntStr(std::vector(j.value().begin(), j.value().end())));+                    break;+                default:+                    // By construction, we will not see these errors here:+                    // - InvalidReceiverTypes+                    // - WalletEncrypted+                    //+                    // If we see these, the user either has generated many addresses, or+                    // was very unlucky with their mnemonic phrase generation:

Mnemonic phrase generation checks that it's possible to produce the keys for the default account and the legacy account.

str4d

comment created time in 4 days

Pull request review commentzcash/zcash

Implement wallet UA RPCs

 UniValue z_getaddressforaccount(const UniValue& params, bool fHelp)     if (!fExperimentalOrchardWallet) {         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: the Orchard wallet experimental extensions are disabled.");     }-    int64_t account = params[0].get_int64();-    if (account < 0 || account >= ZCASH_LEGACY_ACCOUNT) {++    LOCK(pwalletMain->cs_wallet);++    int64_t accountInt = params[0].get_int64();+    if (accountInt < 0 || accountInt >= ZCASH_LEGACY_ACCOUNT) {         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid account number, must be 0 <= account <= (2^31)-2.");     }-    // TODO: Check that the account is known to the wallet.-    std::vector<uint8_t> parsed_diversifier_index;+    libzcash::AccountId account = accountInt;++    std::optional<libzcash::diversifier_index_t> j = std::nullopt;     if (params.size() >= 2) {+        // TODO: Handle '*'         if (params[1].getType() != UniValue::VNUM) {             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid diversifier index, must be an unsigned integer.");         }         auto parsed_diversifier_index_opt = ParseArbitraryInt(params[1].getValStr());         if (!parsed_diversifier_index_opt.has_value()) {             throw JSONRPCError(RPC_INVALID_PARAMETER, "diversifier index must be a decimal integer.");         }-        parsed_diversifier_index = parsed_diversifier_index_opt.value();+        auto parsed_diversifier_index = parsed_diversifier_index_opt.value();         if (parsed_diversifier_index.size() > ZC_DIVERSIFIER_SIZE) {             throw JSONRPCError(RPC_INVALID_PARAMETER, "diversifier index is too large.");         }-    } else {-        // TODO get next unused diversifier index from wallet+        j = libzcash::diversifier_index_t(parsed_diversifier_index);     }-    // TODO:-    // diversifier_t diversifier{};-    // std::copy(parsed_diversifier_index.begin(), parsed_diversifier_index.end(), diversifier.begin());-    UniValue pools(UniValue::VARR);++    std::set<libzcash::ReceiverType> receivers;     if (params.size() >= 3) {-        pools = params[2].get_array();+        const auto& pools = params[2].get_array();         for (unsigned int i = 0; i < pools.size(); i++) {             const std::string& p = pools[i].get_str();-            if (!(p == "transparent" || p == "sapling" || p == "orchard")) {-                throw JSONRPCError(RPC_INVALID_PARAMETER, "pool arguments must be \"transparent\", \"sapling\", or \"orchard\"");+            if (p == "transparent") {+                receivers.insert(ReceiverType::P2PKH);

I guess that any P2SH address in a unified address will have to be constructed manually?

str4d

comment created time in 4 days

Pull request review commentzcash/zcash

Implement wallet UA RPCs

 UniValue z_getaddressforaccount(const UniValue& params, bool fHelp)     if (!fExperimentalOrchardWallet) {         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: the Orchard wallet experimental extensions are disabled.");     }-    int64_t account = params[0].get_int64();-    if (account < 0 || account >= ZCASH_LEGACY_ACCOUNT) {++    LOCK(pwalletMain->cs_wallet);++    int64_t accountInt = params[0].get_int64();+    if (accountInt < 0 || accountInt >= ZCASH_LEGACY_ACCOUNT) {         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid account number, must be 0 <= account <= (2^31)-2.");     }-    // TODO: Check that the account is known to the wallet.-    std::vector<uint8_t> parsed_diversifier_index;+    libzcash::AccountId account = accountInt;++    std::optional<libzcash::diversifier_index_t> j = std::nullopt;     if (params.size() >= 2) {+        // TODO: Handle '*'         if (params[1].getType() != UniValue::VNUM) {             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid diversifier index, must be an unsigned integer.");         }         auto parsed_diversifier_index_opt = ParseArbitraryInt(params[1].getValStr());         if (!parsed_diversifier_index_opt.has_value()) {             throw JSONRPCError(RPC_INVALID_PARAMETER, "diversifier index must be a decimal integer.");         }-        parsed_diversifier_index = parsed_diversifier_index_opt.value();+        auto parsed_diversifier_index = parsed_diversifier_index_opt.value();         if (parsed_diversifier_index.size() > ZC_DIVERSIFIER_SIZE) {             throw JSONRPCError(RPC_INVALID_PARAMETER, "diversifier index is too large.");         }-    } else {-        // TODO get next unused diversifier index from wallet+        j = libzcash::diversifier_index_t(parsed_diversifier_index);     }-    // TODO:-    // diversifier_t diversifier{};-    // std::copy(parsed_diversifier_index.begin(), parsed_diversifier_index.end(), diversifier.begin());-    UniValue pools(UniValue::VARR);++    std::set<libzcash::ReceiverType> receivers;     if (params.size() >= 3) {-        pools = params[2].get_array();+        const auto& pools = params[2].get_array();         for (unsigned int i = 0; i < pools.size(); i++) {             const std::string& p = pools[i].get_str();-            if (!(p == "transparent" || p == "sapling" || p == "orchard")) {-                throw JSONRPCError(RPC_INVALID_PARAMETER, "pool arguments must be \"transparent\", \"sapling\", or \"orchard\"");+            if (p == "transparent") {+                receivers.insert(ReceiverType::P2PKH);+            } else if (p == "sapling") {+                receivers.insert(ReceiverType::Sapling);+            } else {+                throw JSONRPCError(RPC_INVALID_PARAMETER, "pool arguments must be \"transparent\", or \"sapling\"");             }         }     } else {-        // default is all-        pools.push_back("transparent");-        pools.push_back("sapling");-        pools.push_back("orchard");+        // Default is the best and second-best shielded pools, and the transparent pool.+        receivers = {ReceiverType::P2PKH, ReceiverType::Sapling};     }++    EnsureWalletIsUnlocked();

Okay, so the current implementation of the wallet needs to be modified so that we don't need to have the wallet unlocked here; I'll add a ticket to that effect. Essentially, we should cache the UFVKs when the wallet is unlocked. This will do for now though.

str4d

comment created time in 4 days

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentzcash/zcash

rpc: Disable Sprout address generation at Canopy #5368

That's a weird error, nothing in this PR affects the dependencies, and that's a failure in the libsodium build.

LarryRuane

comment created time in 4 days

Pull request review commentzcash/zcash

rpc: Disable Sprout address generation at Canopy #5368

 UniValue z_getnewaddress(const UniValue& params, bool fHelp)         addrType = params[0].get_str();     } -    KeyIO keyIO(Params());+    const auto& chainparams = Params();+    KeyIO keyIO(chainparams);     if (addrType == ADDR_TYPE_SPROUT) {+        int nextBlockHeight = chainActive.Height() + 1-1;

Oh, actually, why not just use chainActive.Height()? Why use nextBlockHeight, we want Sprout address generation to be disabled as of Canopy activation; we don't need to disable it a block early, I don't think.

LarryRuane

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentzcash/zcash

rpc: Disable Sprout address generation at Canopy #5368

 UniValue z_getnewaddress(const UniValue& params, bool fHelp)         addrType = params[0].get_str();     } -    KeyIO keyIO(Params());+    const auto& chainparams = Params();+    KeyIO keyIO(chainparams);     if (addrType == ADDR_TYPE_SPROUT) {+        int nextBlockHeight = chainActive.Height() + 1-1;

why -1?

        int nextBlockHeight = chainActive.Height() + 1;
LarryRuane

comment created time in 4 days

PullRequestReviewEvent
PullRequestReviewEvent

push eventnuttycom/zcash

Kris Nuttycombe

commit sha 2a9e5d2d93e05deae45dcf7b318eac46b183c18e

Use libzcash::RecipientAddress for z_sendmany recipients.

view details

push time in 4 days

push eventnuttycom/zcash

Kris Nuttycombe

commit sha fe0c5306f55c4bb4f3205d226a195a00f47d875f

Add RecipientAddress type.

view details

push time in 4 days

push eventnuttycom/zcash

Kris Nuttycombe

commit sha 5501e2fafb75bfa875d1dfac3bbb803611378fc0

Add CWallet::GetAccountForPaymentSource Also, ensure that we validate that we have the appropriate spending keys when detecting the account that corresponds to a payment address.

view details

push time in 4 days

Pull request review commentzcash/librustzcash

Add auto-shielding to the data access API

 where     } } +pub trait AddressCodec<P>

This doesn't quite have the same semantics as zcash_address provides: this does the full decoding to domain types, whereas zcash_address only provides decoding to bytes. I think that this is generally a useful trait to have; I'm not sure if it could be made crate-private given that I think it's likely used in public APIs.

nuttycom

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentzcash/librustzcash

Add auto-shielding to the data access API

 where             .map_err(Error::Builder)?;     } -    match to {-        RecipientAddress::Shielded(to) => {-            builder.add_sapling_output(ovk, to.clone(), value, memo.clone())-        }--        RecipientAddress::Transparent(to) => builder.add_transparent_output(&to, value),+    for payment in request.payments() {+        match &payment.recipient_address {+            RecipientAddress::Shielded(to) => builder+                .add_sapling_output(+                    ovk,+                    to.clone(),+                    payment.amount,+                    payment.memo.clone().unwrap_or_else(MemoBytes::empty),+                )+                .map_err(Error::Builder),+            RecipientAddress::Transparent(to) => {+                if payment.memo.is_some() {+                    Err(Error::MemoForbidden)+                } else {+                    builder+                        .add_transparent_output(&to, payment.amount)+                        .map_err(Error::Builder)+                }+            }+        }?     }-    .map_err(Error::Builder)?;      let (tx, tx_metadata) = builder.build(&prover).map_err(Error::Builder)?; -    let output_index = match to {-        // Sapling outputs are shuffled, so we need to look up where the output ended up.-        RecipientAddress::Shielded(_) => match tx_metadata.output_index(0) {-            Some(idx) => idx,-            None => panic!("Output 0 should exist in the transaction"),-        },-        RecipientAddress::Transparent(addr) => {-            let script = addr.script();-            tx.transparent_bundle()-                .and_then(|b| {-                    b.vout-                        .iter()-                        .enumerate()-                        .find(|(_, tx_out)| tx_out.script_pubkey == script)-                })-                .map(|(index, _)| index)-                .expect("we sent to this address")+    let sent_outputs = request.payments().iter().enumerate().map(|(i, payment)| {+        let idx = match &payment.recipient_address {+            // Sapling outputs are shuffled, so we need to look up where the output ended up.+            RecipientAddress::Shielded(_) =>+                tx_metadata.output_index(i).expect("An output should exist in the transaction for each shielded payment."),+            RecipientAddress::Transparent(addr) => {+                let script = addr.script();+                tx.transparent_bundle()+                    .and_then(|b| {+                        b.vout+                            .iter()+                            .enumerate()+                            .find(|(_, tx_out)| tx_out.script_pubkey == script)+                    })+                    .map(|(index, _)| index)+                    .expect("An output should exist in the transaction for each transparent payment.")+            }+        };++        SentTransactionOutput {+            output_index: idx,+            recipient_address: &payment.recipient_address,+            value: payment.amount,+            memo: payment.memo.clone()         }-    };+    }).collect();      wallet_db.store_sent_tx(&SentTransaction {         tx: &tx,         created: time::OffsetDateTime::now_utc(),-        output_index,+        outputs: sent_outputs,         account,-        recipient_address: to,-        value,-        memo,+        utxos_spent: vec![],+    })+}++/// Constructs a transaction that consumes available transparent UTXOs belonging to+/// the specified secret key, and sends them to the default address for the provided Sapling+/// extended full viewing key.+///+/// This procedure will not attempt to shield transparent funds if the total amount being shielded+/// is less than the default fee to send the transaction. Fees will be paid only from the transparent+/// UTXOs being consumed.+///+/// Parameters:+/// * `wallet_db`: A read/write reference to the wallet database+/// * `params`: Consensus parameters+/// * `prover`: The TxProver to use in constructing the shielded transaction.+/// * `sk`: The secp256k1 secret key that will be used to detect and spend transparent+///   UTXOs.+/// * `extfvk`: The extended full viewing key that will be used to produce the+///   Sapling address to which funds will be sent.+/// * `account`: The ZIP32 account identifier associated with the the extended+///   full viewing key. This procedure will return an error if this does not correctly+///   correspond to `extfvk`.+/// * `min_confirmations`: The minimum number of confirmations that a previously+///   received UTXO must have in the blockchain in order to be considered for being+///   spent.+#[cfg(feature = "transparent-inputs")]+#[allow(clippy::too_many_arguments)]+pub fn shield_transparent_funds<E, N, P, D, R>(+    wallet_db: &mut D,+    params: &P,+    prover: impl TxProver,+    sk: &secp256k1::SecretKey,+    extfvk: &ExtendedFullViewingKey,+    account: AccountId,+    memo: &MemoBytes,+    min_confirmations: u32,+) -> Result<D::TxRef, E>+where+    E: From<Error<N>>,+    P: consensus::Parameters,+    R: Copy + Debug,+    D: WalletWrite<Error = E, TxRef = R>,+{+    // Check that the ExtendedSpendingKey we have been given corresponds to the+    // ExtendedFullViewingKey for the account we are spending from.+    if !wallet_db.is_valid_account_extfvk(account, &extfvk)? {+        return Err(E::from(Error::InvalidExtSk(account)));+    }++    let (latest_scanned_height, latest_anchor) = wallet_db+        .get_target_and_anchor_heights(min_confirmations)+        .and_then(|x| x.ok_or_else(|| Error::ScanRequired.into()))?;++    // derive the corresponding t-address+    let taddr = derive_transparent_address_from_secret_key(sk);++    // derive own shielded address from the provided extended spending key+    let z_address = extfvk.default_address().1;+    let ovk = extfvk.fvk.ovk;

We won't need to now that we have ZIP-316 specifying how to derive OVKs for transparent addresses.

nuttycom

comment created time in 4 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentzcash/librustzcash

Add auto-shielding to the data access API

 where             .map_err(Error::Builder)?;     } -    match to {-        RecipientAddress::Shielded(to) => {-            builder.add_sapling_output(ovk, to.clone(), value, memo.clone())-        }--        RecipientAddress::Transparent(to) => builder.add_transparent_output(&to, value),+    for payment in request.payments() {+        match &payment.recipient_address {+            RecipientAddress::Shielded(to) => builder+                .add_sapling_output(+                    ovk,+                    to.clone(),+                    payment.amount,+                    payment.memo.clone().unwrap_or_else(MemoBytes::empty),+                )+                .map_err(Error::Builder),+            RecipientAddress::Transparent(to) => {+                if payment.memo.is_some() {+                    Err(Error::MemoForbidden)+                } else {+                    builder+                        .add_transparent_output(&to, payment.amount)+                        .map_err(Error::Builder)+                }+            }+        }?     }-    .map_err(Error::Builder)?;      let (tx, tx_metadata) = builder.build(&prover).map_err(Error::Builder)?; -    let output_index = match to {-        // Sapling outputs are shuffled, so we need to look up where the output ended up.-        RecipientAddress::Shielded(_) => match tx_metadata.output_index(0) {-            Some(idx) => idx,-            None => panic!("Output 0 should exist in the transaction"),-        },-        RecipientAddress::Transparent(addr) => {-            let script = addr.script();-            tx.transparent_bundle()-                .and_then(|b| {-                    b.vout-                        .iter()-                        .enumerate()-                        .find(|(_, tx_out)| tx_out.script_pubkey == script)-                })-                .map(|(index, _)| index)-                .expect("we sent to this address")+    let sent_outputs = request.payments().iter().enumerate().map(|(i, payment)| {+        let idx = match &payment.recipient_address {+            // Sapling outputs are shuffled, so we need to look up where the output ended up.+            RecipientAddress::Shielded(_) =>+                tx_metadata.output_index(i).expect("An output should exist in the transaction for each shielded payment."),+            RecipientAddress::Transparent(addr) => {+                let script = addr.script();+                tx.transparent_bundle()+                    .and_then(|b| {+                        b.vout+                            .iter()+                            .enumerate()+                            .find(|(_, tx_out)| tx_out.script_pubkey == script)+                    })+                    .map(|(index, _)| index)+                    .expect("An output should exist in the transaction for each transparent payment.")+            }+        };++        SentTransactionOutput {+            output_index: idx,+            recipient_address: &payment.recipient_address,+            value: payment.amount,+            memo: payment.memo.clone()         }-    };+    }).collect();      wallet_db.store_sent_tx(&SentTransaction {         tx: &tx,         created: time::OffsetDateTime::now_utc(),-        output_index,+        outputs: sent_outputs,         account,-        recipient_address: to,-        value,-        memo,+        utxos_spent: vec![],+    })+}++/// Constructs a transaction that consumes available transparent UTXOs belonging to+/// the specified secret key, and sends them to the default address for the provided Sapling+/// extended full viewing key.

Prior to ZIP-316 we didn't have a well-defined OVK for transparent addresses, and this was written almost a year ago, and the destination OVK was the only one we had available that didn't require us to create additional wallet state to store the key.

nuttycom

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentzcash/librustzcash

Add auto-shielding to the data access API

 impl RecipientAddress {      pub fn encode<P: consensus::Parameters>(&self, params: &P) -> String {         match self {-            RecipientAddress::Shielded(pa) => {-                encode_payment_address(params.hrp_sapling_payment_address(), pa)-            }-            RecipientAddress::Transparent(addr) => encode_transparent_address(-                &params.b58_pubkey_address_prefix(),-                &params.b58_script_address_prefix(),-                addr,-            ),+            RecipientAddress::Shielded(pa) => encode_payment_address_p(params, pa),+            RecipientAddress::Transparent(addr) => encode_transparent_address_p(params, addr),

I think that what this means is that we need to write a function from the zcash_address types to the internal RecipientAddress type, and then chain those two.

nuttycom

comment created time in 4 days

issue commentzcash/zcash

New RPC: z_getnewaccount

Notes from a discussion in Slack:

I think that this RPC method should not return the default address. There are a few reasons for this:

  • First, we would like to encourage our users to avoid reuse of unified addresses that contain transparent components. Ideally, we'd like our users to migrate their workflows to be account-centric rather than address-centric, and separating address generation from account generation helps with this.

Accounts are not associated with a specific set of receivers; instead, selection of receiver types is performed only at address generation, and inside of zcashd the internal USK and UFVK for every account support all implemented receiver types. This is important for forward compatibility: we only want the UFVK to be cached in memory; we don't want it to persist with a subset of the possible item types. The same is true of the USK; we want to regenerate it from the mnemonic seed for the account as needed. That way, when we add future protocols there's essentially nothing that needs to be updated in the wallet's data store, because we don't store anything that needs to be updated!

When you look up the UFVKId for a given receiver, you get enough information to reproduce the address you generated from which that receiver was extracted, as it was at the time it was generated. The UFVKId will change when we add a new pool, and newly created addresses will map their receivers to the new UFVKId. Importantly, multiple UFVKIds can map to the same logical UFVK, so the metadata of newly generated addresses will refer to the "updated" UFVKId.

str4d

comment created time in 5 days

push eventnuttycom/zcash

Kris Nuttycombe

commit sha ca2a8e967d0ea5169abacec1be3e9ed6c040afc7

Support unified addresses in CWallet::FindSpendableInputs

view details

push time in 5 days

push eventnuttycom/librustzcash

Kris Nuttycombe

commit sha c66bb892baf7e54437be7341c163f40909a64b43

Rename script_code to script_pubkey in zip244 test vectors.

view details

push time in 5 days

push eventnuttycom/librustzcash

Kris Nuttycombe

commit sha 6232c7336770077241b2e3c7428a35e188057d86

Make transparent signatures commit to all input amounts & scripts. Transparent UTXOs are referred as pair of previous txid and index. In order to verify UTXO's amount in HWW (hardware wallet), whole previous transaction containing this UTXO must be streamed into the device. This increases complexity of signing process significantly. zcash/zips#574 identifies this problem and suggests a modification to ZIP-244 to resolve this issue, by adding three new fields to section S.2 of the signature hash.

view details

Kris Nuttycombe

commit sha 5b25650ee68aee35f0e416cc777c0e3369c20156

Make hash_type a property of the SignableInput::Transparent

view details

Kris Nuttycombe

commit sha 94db017413355126ca7c6ded8f5ca6b73eb68d8c

Update test vectors.

view details

Kris Nuttycombe

commit sha b0dcde442a17aee25a1b65497c03f42bd0506681

Update v5 transparent signature hashes to always commit to scriptPubKey

view details

Kris Nuttycombe

commit sha c808f365a854bec0f8bbd44d4c9b8f7628fe0518

Rename script_code to script_pubkey in zip244 test vectors. Also, cargo fmt.

view details

push time in 5 days

push eventnuttycom/librustzcash

Kris Nuttycombe

commit sha 167a4045ef294d1168acb204a2745332e228d846

Rename script_code to script_pubkey in zip244 test vectors. Also, cargo fmt.

view details

push time in 5 days

push eventnuttycom/zcash

Kris Nuttycombe

commit sha b74acf81b915a42d2dd5a1328ade061a5f865b5d

Rename FromAccount -> AccountPaymentSource

view details

Kris Nuttycombe

commit sha a56c0eed85ac0c095f4acbca56000991bfb1a3e0

WIP

view details

push time in 5 days

more