#[non_exhaustive]pub enum ProposalError {
Show 24 variants
RequestTotalInvalid,
Overflow,
BalanceError {
input_total: Zatoshis,
output_total: Zatoshis,
},
ShieldingInvalid,
AnchorNotFound(BlockHeight),
MissingShieldedAnchor,
ReferenceError(StepOutput),
StepDoubleSpend(StepOutput),
ChainDoubleSpend(OutputRef),
InputsLocked(OutputRef),
PaymentPoolsMismatch,
SpendsChange(StepOutput),
Zip321(Zip321Error),
PaymentAmountMissing(usize),
EphemeralOutputLeftUnspent(StepOutput),
PaysTexFromShielded,
EphemeralOutputsInvalid,
EphemeralAddressLinkability,
ShieldingRequiresShieldedRecipient,
IncompatibleTxVersion(BranchId),
OrchardReceiverRequiresIronwood(TxVersion),
OrchardPoolValueCreation {
input_total: Zatoshis,
output_total: Zatoshis,
},
OrchardPoolPayment(usize),
TransactionTooLarge {
estimated_size: usize,
limit: usize,
sapling_input_count: usize,
orchard_input_count: usize,
ironwood_input_count: usize,
},
}Expand description
Errors that can occur in construction of a Step.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
RequestTotalInvalid
The total output value of the transaction request is not a valid Zcash amount.
Overflow
The total of transaction inputs overflows the valid range of Zcash values.
BalanceError
The input total and output total of the payment request are not equal to one another. The sum of transaction outputs, change, and fees is required to be exactly equal to the value of provided inputs.
ShieldingInvalid
The is_shielding flag may only be set to true under the following conditions:
- The total of transparent inputs is nonzero
- There exist no Sapling inputs
- There provided transaction request is empty; i.e. the only output values specified are change and fee amounts.
AnchorNotFound(BlockHeight)
No anchor information could be obtained for the specified block height.
MissingShieldedAnchor
A proposal step produces a shielded bundle — it spends shielded notes, pays to a shielded pool, or returns shielded change — but does not specify an anchor height against which its shielded-tree lookups are performed. Only a purely transparent step may omit its anchor.
ReferenceError(StepOutput)
A reference to the output of a prior step is invalid.
StepDoubleSpend(StepOutput)
An attempted double-spend of a prior step output was detected.
ChainDoubleSpend(OutputRef)
An attempted double-spend of an output belonging to the wallet was detected.
InputsLocked(OutputRef)
An input selected by the proposal could not be locked, because a concurrent proposal or PCZT already holds a lock on it.
This is a transient condition, not a defect in the proposal itself: the wrapped output was spendable when it was selected, but another in-flight proposal locked it first. Callers should treat this as “the account is busy” and retry proposal creation; the retry will select around the locked output (or fail with an insufficient-funds error if no other outputs are available).
PaymentPoolsMismatch
There was a mismatch between the payments in the proposal’s transaction request and the payment pool selection values.
SpendsChange(StepOutput)
The proposal tried to spend a change output. Mark the ChangeValue as ephemeral if this is intended.
Zip321(Zip321Error)
The proposal results in an invalid payment request according to ZIP-321.
PaymentAmountMissing(usize)
The ZIP 321 payment request at the wrapped index lacked payment amount information.
EphemeralOutputLeftUnspent(StepOutput)
transparent-inputs only.A proposal step created an ephemeral output that was not spent in any later step.
PaysTexFromShielded
transparent-inputs only.The proposal included a payment to a TEX address and a spend from a shielded input in the same step.
EphemeralOutputsInvalid
transparent-inputs only.The change strategy provided to input selection failed to correctly generate an ephemeral change output when needed for sending to a TEX address.
EphemeralAddressLinkability
transparent-inputs only.The requested proposal would link activity on an ephemeral address to other wallet activity.
ShieldingRequiresShieldedRecipient
transparent-inputs only.A shielding proposal was constructed with a destination address that has no shielded receiver. Shielding requires the destination to be able to receive shielded value.
IncompatibleTxVersion(BranchId)
The transaction version requested is not compatible with the consensus branch for which the transaction is intended.
OrchardReceiverRequiresIronwood(TxVersion)
After NU6.3 activation, a payment to an Orchard receiver must be delivered through the Ironwood pool, which requires a version 6 transaction. The explicitly-requested transaction version has no Ironwood bundle, so it cannot carry the payment. (The Orchard turnstile is a consensus rule after NU6.3: no payment may add value to the Orchard pool, so such a payment cannot be delivered as a plain Orchard output either.)
OrchardPoolValueCreation
orchard only.After Ironwood activation, a proposal step would create value in the Orchard pool.
The turnstile only permits value to leave the pool: a step may return change to it
only when strictly less value returns than the step’s Orchard inputs remove.
(Payments may never be directed to the Orchard pool after Ironwood activation;
payment classification maintains that invariant, and step construction enforces it
via ProposalError::OrchardPoolPayment.)
Fields
input_total: ZatoshisThe total value of the Orchard notes spent by the step.
output_total: ZatoshisThe total value of the Orchard-pool change outputs created by the step.
OrchardPoolPayment(usize)
orchard only.After Ironwood activation, the payment at the wrapped index of the step’s transaction request was directed to the Orchard pool. The turnstile only permits value to leave the pool, so no payment may be directed to it; payment classification routes Orchard-receiver payments to the Ironwood pool instead.
TransactionTooLarge
The transaction the step describes would exceed the maximum size a Zcash block may
carry, and so cannot be included in any block. The serialized size of the step’s
transaction was estimated from its inputs, outputs, and change, using conservative
per-element byte costs; the estimate exceeds MAX_BLOCK_BYTES.
MAX_BLOCK_BYTES is the block size limit, not a per-transaction limit: a
transaction that fits just under it still cannot be mined, because the block must
also carry its header and coinbase transaction. Passing the gate is therefore
necessary but not sufficient for mineability near the boundary; the builder is the
final authority.
Recovery for a caller that receives this error: reduce the number of inputs by
lowering the payment amount or by consolidating small notes via send-to-self
transactions before retrying. Each consolidation round must be mined and its note
commitments anchored before the resulting notes are spendable, so recovery spans
multiple confirmations. For propose_send_max this error is a dead end — there is
no smaller amount to back off to — and requires a multi-transaction strategy.
Fields
sapling_input_count: usizeThe number of Sapling inputs the step spends, including prior-step inputs. Carried so a wallet can explain the situation in terms of notes rather than bytes; the different shielded pools have very different per-input costs.
Trait Implementations§
Source§impl Clone for ProposalError
impl Clone for ProposalError
Source§impl Debug for ProposalError
impl Debug for ProposalError
Source§impl Display for ProposalError
impl Display for ProposalError
Source§impl Error for ProposalError
impl Error for ProposalError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl<DE, TE, SE, FE, CE, N> From<ProposalError> for Error<DE, TE, SE, FE, CE, N>
impl<DE, TE, SE, FE, CE, N> From<ProposalError> for Error<DE, TE, SE, FE, CE, N>
Source§fn from(e: ProposalError) -> Self
fn from(e: ProposalError) -> Self
Source§impl<E, S, C, N> From<ProposalError> for InputSelectorError<E, S, C, N>
impl<E, S, C, N> From<ProposalError> for InputSelectorError<E, S, C, N>
Source§fn from(err: ProposalError) -> Self
fn from(err: ProposalError) -> Self
Auto Trait Implementations§
impl Freeze for ProposalError
impl RefUnwindSafe for ProposalError
impl Send for ProposalError
impl Sync for ProposalError
impl Unpin for ProposalError
impl UnsafeUnpin for ProposalError
impl UnwindSafe for ProposalError
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> PossiblyOption<T> for T
impl<T> PossiblyOption<T> for T
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.§impl<T> TryConv for T
impl<T> TryConv for T
§impl<T> TryIntoSlug for T
impl<T> TryIntoSlug for T
§fn try_into_slug(&self) -> Result<Slug, BadSlug>
fn try_into_slug(&self) -> Result<Slug, BadSlug>
self into a Slug, if it has the right syntax