Ensure that prevout, extension_id & mode data can be signed in builder.
This commit is contained in:
parent
1a8168e1c9
commit
5a432b5e2b
|
@ -354,7 +354,7 @@ impl<'a, B: ExtensionTxBuilder<'a>> DemoBuilder<&mut B> {
|
|||
}
|
||||
|
||||
self.txn_builder
|
||||
.add_tze_input(self.extension_id, prevout, move |_| {
|
||||
.add_tze_input(self.extension_id, open::MODE, prevout, move |_| {
|
||||
Ok(Witness::open(preimage_1))
|
||||
})
|
||||
.map_err(DemoBuildError::BaseBuilderError)?;
|
||||
|
@ -362,7 +362,7 @@ impl<'a, B: ExtensionTxBuilder<'a>> DemoBuilder<&mut B> {
|
|||
self.txn_builder
|
||||
.add_tze_output(
|
||||
self.extension_id,
|
||||
transfer_amount,
|
||||
transfer_amount,
|
||||
&Precondition::close(hash_2),
|
||||
)
|
||||
.map_err(DemoBuildError::BaseBuilderError)
|
||||
|
@ -397,7 +397,7 @@ impl<'a, B: ExtensionTxBuilder<'a>> DemoBuilder<&mut B> {
|
|||
}
|
||||
|
||||
self.txn_builder
|
||||
.add_tze_input(self.extension_id, prevout, move |_| {
|
||||
.add_tze_input(self.extension_id, close::MODE, prevout, move |_| {
|
||||
Ok(Witness::close(preimage_2))
|
||||
})
|
||||
.map_err(DemoBuildError::BaseBuilderError)
|
||||
|
|
|
@ -27,7 +27,7 @@ pub trait ToPayload {
|
|||
|
||||
/// A condition that can be used to encumber transparent funds.
|
||||
///
|
||||
/// This struct is an intermediate representation between the
|
||||
/// This struct is an intermediate representation between the
|
||||
/// serialized binary format which is used inside of a transaction
|
||||
/// and extension-specific types. The payload field of this struct
|
||||
/// is treated as opaque to all but extension corresponding to the
|
||||
|
@ -51,7 +51,7 @@ impl Precondition {
|
|||
}
|
||||
}
|
||||
|
||||
/// Attempt to parse an extension-specific precondition value from the
|
||||
/// Attempt to parse an extension-specific precondition value from the
|
||||
/// intermediate representation.
|
||||
pub fn try_to<P: FromPayload>(&self) -> Result<P, P::Error> {
|
||||
P::from_payload(self.mode, &self.payload)
|
||||
|
@ -61,7 +61,7 @@ impl Precondition {
|
|||
/// Data that satisfies the precondition for prior encumbered funds, enabling them to be
|
||||
/// spent.
|
||||
///
|
||||
/// This struct is an intermediate representation between the
|
||||
/// This struct is an intermediate representation between the
|
||||
/// serialized binary format which is used inside of a transaction
|
||||
/// and extension-specific types. The payload field of this struct
|
||||
/// is treated as opaque to all but extension corresponding to the
|
||||
|
@ -85,7 +85,7 @@ impl Witness {
|
|||
}
|
||||
}
|
||||
|
||||
/// Attempt to parse an extension-specific witness value from the
|
||||
/// Attempt to parse an extension-specific witness value from the
|
||||
/// intermediate representation.
|
||||
pub fn try_to<P: FromPayload>(&self) -> Result<P, P::Error> {
|
||||
P::from_payload(self.mode, &self.payload)
|
||||
|
@ -153,10 +153,10 @@ pub trait ExtensionTxBuilder<'a> {
|
|||
type BuildError;
|
||||
|
||||
/// Add a TZE input to the transaction under construction by providing a witness
|
||||
/// to a precondition identified by a prior outpoint.
|
||||
/// to a precondition identified by a prior outpoint.
|
||||
///
|
||||
/// The `witness_builder` function allows the transaction builder to provide extra
|
||||
/// contextual information from the transaction under construction to be used
|
||||
/// contextual information from the transaction under construction to be used
|
||||
/// in the production of this witness (for example, so that the witness may
|
||||
/// internally make commitments based upon this information.) For the standard
|
||||
/// transaction builder, the value provided here is the transaction under
|
||||
|
@ -164,6 +164,7 @@ pub trait ExtensionTxBuilder<'a> {
|
|||
fn add_tze_input<WBuilder, W: ToPayload>(
|
||||
&mut self,
|
||||
extension_id: u32,
|
||||
mode: u32,
|
||||
prevout: (OutPoint, TzeOut),
|
||||
witness_builder: WBuilder,
|
||||
) -> Result<(), Self::BuildError>
|
||||
|
|
|
@ -51,6 +51,7 @@ pub enum Error {
|
|||
InvalidAmount,
|
||||
NoChangeAddress,
|
||||
SpendProof,
|
||||
TzeWitnessModeMismatch(u32, u32),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
|
@ -67,6 +68,8 @@ impl fmt::Display for Error {
|
|||
Error::InvalidAmount => write!(f, "Invalid amount"),
|
||||
Error::NoChangeAddress => write!(f, "No change address specified or discoverable"),
|
||||
Error::SpendProof => write!(f, "Failed to create Sapling spend proof"),
|
||||
Error::TzeWitnessModeMismatch(expected, actual) =>
|
||||
write!(f, "TZE witness builder returned a mode that did not match the mode with which the input was initially constructed: expected = {:?}, actual = {:?}", expected, actual),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +269,7 @@ impl TransparentInputs {
|
|||
|
||||
struct TzeInputInfo<'a, BuildCtx> {
|
||||
prevout: TzeOut,
|
||||
builder: Box<dyn FnOnce(&BuildCtx) -> Result<TzeIn, Error> + 'a>,
|
||||
builder: Box<dyn FnOnce(&BuildCtx) -> Result<(u32, Vec<u8>), Error> + 'a>,
|
||||
}
|
||||
|
||||
struct TzeInputs<'a, BuildCtx> {
|
||||
|
@ -278,27 +281,13 @@ impl<'a, BuildCtx> TzeInputs<'a, BuildCtx> {
|
|||
TzeInputs { builders: vec![] }
|
||||
}
|
||||
|
||||
fn push<WBuilder, W: ToPayload>(
|
||||
&mut self,
|
||||
extension_id: u32,
|
||||
(outpoint, tzeout): (OutPoint, TzeOut),
|
||||
builder: WBuilder,
|
||||
) where
|
||||
fn push<WBuilder, W: ToPayload>(&mut self, tzeout: TzeOut, builder: WBuilder)
|
||||
where
|
||||
WBuilder: 'a + FnOnce(&BuildCtx) -> Result<W, Error>,
|
||||
{
|
||||
self.builders.push(TzeInputInfo {
|
||||
prevout: tzeout,
|
||||
builder: Box::new(move |ctx| {
|
||||
let (mode, payload) = builder(&ctx).map(|x| x.to_payload())?;
|
||||
Ok(TzeIn {
|
||||
prevout: outpoint,
|
||||
witness: tze::Witness {
|
||||
extension_id,
|
||||
mode,
|
||||
payload,
|
||||
},
|
||||
})
|
||||
}),
|
||||
builder: Box::new(move |ctx| builder(&ctx).map(|x| x.to_payload())),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -784,7 +773,7 @@ impl<'a, P: consensus::Parameters, R: RngCore + CryptoRng> Builder<'a, P, R> {
|
|||
};
|
||||
|
||||
// // Create TZE input witnesses
|
||||
for tze_in in self.tze_inputs.builders {
|
||||
for (i, tze_in) in self.tze_inputs.builders.into_iter().enumerate() {
|
||||
// Need to enable witness to commit to the amount.
|
||||
// - So hardware wallets "know" the amount without having to be sent all the
|
||||
// prior TZE outputs to which this witness gives evidence.
|
||||
|
@ -793,7 +782,13 @@ impl<'a, P: consensus::Parameters, R: RngCore + CryptoRng> Builder<'a, P, R> {
|
|||
// (Or make it part of the sighash?)
|
||||
// - TODO: Check whether transparent inputs committing to script_pubkey was
|
||||
// only so that hardware wallets "knew" what address was being spent from.
|
||||
self.mtx.tze_inputs.push((tze_in.builder)(&self.mtx)?);
|
||||
let (mode, payload) = (tze_in.builder)(&self.mtx)?;
|
||||
let mut current = self.mtx.tze_inputs.get_mut(i).unwrap();
|
||||
if mode != current.witness.mode {
|
||||
return Err(Error::TzeWitnessModeMismatch(current.witness.mode, mode));
|
||||
}
|
||||
|
||||
current.witness.payload = payload;
|
||||
}
|
||||
|
||||
// Transparent signatures
|
||||
|
@ -816,13 +811,17 @@ impl<'a, P: consensus::Parameters, R: RngCore + CryptoRng> ExtensionTxBuilder<'a
|
|||
fn add_tze_input<WBuilder, W: ToPayload>(
|
||||
&mut self,
|
||||
extension_id: u32,
|
||||
prevout: (OutPoint, TzeOut),
|
||||
mode: u32,
|
||||
(outpoint, prevout): (OutPoint, TzeOut),
|
||||
witness_builder: WBuilder,
|
||||
) -> Result<(), Self::BuildError>
|
||||
where
|
||||
WBuilder: 'a + (FnOnce(&Self::BuildCtx) -> Result<W, Self::BuildError>),
|
||||
{
|
||||
self.tze_inputs.push(extension_id, prevout, witness_builder);
|
||||
self.mtx
|
||||
.tze_inputs
|
||||
.push(TzeIn::new(outpoint, extension_id, mode));
|
||||
self.tze_inputs.push(prevout, witness_builder);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -132,6 +132,16 @@ fn to_io_error(_: std::num::TryFromIntError) -> io::Error {
|
|||
}
|
||||
|
||||
impl TzeIn {
|
||||
pub fn new(prevout: OutPoint, extension_id: u32, mode: u32) -> Self {
|
||||
TzeIn {
|
||||
prevout,
|
||||
witness: tze::Witness {
|
||||
extension_id,
|
||||
mode,
|
||||
payload: vec![],
|
||||
},
|
||||
}
|
||||
}
|
||||
pub fn read<R: Read>(mut reader: &mut R) -> io::Result<Self> {
|
||||
let prevout = OutPoint::read(&mut reader)?;
|
||||
|
||||
|
|
Loading…
Reference in New Issue