Add a protobuf representation for transaction proposals.

Co-authored-by: Kris Nuttycombe <kris@nutty.land>
This commit is contained in:
sasha 2023-05-22 16:08:20 -07:00 committed by Kris Nuttycombe
parent 2d6a02eb2d
commit 572563338b
5 changed files with 241 additions and 0 deletions

1
.gitattributes vendored
View File

@ -1,2 +1,3 @@
zcash_client_backend/src/proto/compact_formats.rs linguist-generated=true
zcash_client_backend/src/proto/service.rs linguist-generated=true
zcash_client_backend/src/proto/proposal.rs linguist-generated=true

View File

@ -4,6 +4,9 @@ use std::io;
use std::path::{Path, PathBuf};
const COMPACT_FORMATS_PROTO: &str = "proto/compact_formats.proto";
const PROPOSAL_PROTO: &str = "proto/proposal.proto";
const SERVICE_PROTO: &str = "proto/service.proto";
fn main() -> io::Result<()> {
@ -71,6 +74,15 @@ fn build() -> io::Result<()> {
)
.compile(&[SERVICE_PROTO], &["proto/"])?;
// Build the proposal types.
tonic_build::compile_protos(PROPOSAL_PROTO)?;
// Copy the generated types into the source tree so changes can be committed.
fs::copy(
out.join("cash.z.wallet.sdk.ffi.rs"),
"src/proto/proposal.rs",
)?;
// Copy the generated types into the source tree so changes can be committed. The
// file has the same name as for the compact format types because they have the
// same package, but we've set things up so this only contains the service types.

View File

@ -0,0 +1,86 @@
// Copyright (c) 2023 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
syntax = "proto3";
package cash.z.wallet.sdk.ffi;
// A data structure that describes the inputs to be consumed and outputs to
// be produced in a proposed transaction.
message Proposal {
uint32 protoVersion = 1;
// ZIP 321 serialized transaction request
string transactionRequest = 2;
// The transparent UTXOs to use as inputs to the transaction.
repeated ProposedInput transparentInputs = 3;
// The Sapling input notes and anchor height to be used in creating the transaction.
SaplingInputs saplingInputs = 4;
// The total value, fee amount, and change outputs of the proposed
// transaction
TransactionBalance balance = 5;
// The fee rule used in constructing this proposal
FeeRule feeRule = 6;
// The target height for which the proposal was constructed
//
// The chain must contain at least this many blocks in order for the proposal to
// be executed.
uint32 minTargetHeight = 7;
// A flag indicating whether the proposal is for a shielding transaction,
// used for determining which OVK to select for wallet-internal outputs.
bool isShielding = 8;
}
message SaplingInputs {
// Returns the Sapling anchor height to be used in creating the transaction.
uint32 anchorHeight = 1;
// The unique identifier and amount for each proposed Sapling input
repeated ProposedInput inputs = 2;
}
// The unique identifier and amount for each proposed input.
message ProposedInput {
bytes txid = 1;
uint32 index = 2;
uint64 value = 3;
}
// The fee rule used in constructing a Proposal
enum FeeRule {
// Protobuf requires that enums have a zero descriminant as the default
// value. However, we need to require that a known fee rule is selected,
// and we do not want to fall back to any default, so sending the
// FeeRuleNotSpecified value will be treated as an error.
FeeRuleNotSpecified = 0;
// 10000 ZAT
PreZip313 = 1;
// 1000 ZAT
Zip313 = 2;
// MAX(10000, 5000 * logical_actions) ZAT
Zip317 = 3;
}
// The proposed change outputs and fee amount.
message TransactionBalance {
repeated ChangeValue proposedChange = 1;
uint64 feeRequired = 2;
}
// An enumeration of change value types.
message ChangeValue {
oneof value {
SaplingChange saplingValue = 1;
}
}
// An object wrapper for memo bytes, to facilitate representing the
// `change_memo == None` case.
message MemoBytes {
bytes value = 1;
}
// The amount and memo for a proposed Sapling change output.
message SaplingChange {
uint64 amount = 1;
MemoBytes memo = 2;
}

View File

@ -18,6 +18,11 @@ use zcash_note_encryption::{EphemeralKeyBytes, COMPACT_NOTE_SIZE};
#[allow(clippy::derive_partial_eq_without_eq)]
pub mod compact_formats;
#[rustfmt::skip]
#[allow(unknown_lints)]
#[allow(clippy::derive_partial_eq_without_eq)]
pub mod proposal;
#[rustfmt::skip]
#[allow(unknown_lints)]
#[allow(clippy::derive_partial_eq_without_eq)]

137
zcash_client_backend/src/proto/proposal.rs generated Normal file
View File

@ -0,0 +1,137 @@
/// A data structure that describes the inputs to be consumed and outputs to
/// be produced in a proposed transaction.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Proposal {
#[prost(uint32, tag = "1")]
pub proto_version: u32,
/// ZIP 321 serialized transaction request
#[prost(string, tag = "2")]
pub transaction_request: ::prost::alloc::string::String,
/// The transparent UTXOs to use as inputs to the transaction.
#[prost(message, repeated, tag = "3")]
pub transparent_inputs: ::prost::alloc::vec::Vec<ProposedInput>,
/// The Sapling input notes and anchor height to be used in creating the transaction.
#[prost(message, optional, tag = "4")]
pub sapling_inputs: ::core::option::Option<SaplingInputs>,
/// The total value, fee amount, and change outputs of the proposed
/// transaction
#[prost(message, optional, tag = "5")]
pub balance: ::core::option::Option<TransactionBalance>,
/// The fee rule used in constructing this proposal
#[prost(enumeration = "FeeRule", tag = "6")]
pub fee_rule: i32,
/// The target height for which the proposal was constructed
///
/// The chain must contain at least this many blocks in order for the proposal to
/// be executed.
#[prost(uint32, tag = "7")]
pub min_target_height: u32,
/// A flag indicating whether the proposal is for a shielding transaction,
/// used for determining which OVK to select for wallet-internal outputs.
#[prost(bool, tag = "8")]
pub is_shielding: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SaplingInputs {
/// Returns the Sapling anchor height to be used in creating the transaction.
#[prost(uint32, tag = "1")]
pub anchor_height: u32,
/// The unique identifier and amount for each proposed Sapling input
#[prost(message, repeated, tag = "2")]
pub inputs: ::prost::alloc::vec::Vec<ProposedInput>,
}
/// The unique identifier and amount for each proposed input.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProposedInput {
#[prost(bytes = "vec", tag = "1")]
pub txid: ::prost::alloc::vec::Vec<u8>,
#[prost(uint32, tag = "2")]
pub index: u32,
#[prost(uint64, tag = "3")]
pub value: u64,
}
/// The proposed change outputs and fee amount.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TransactionBalance {
#[prost(message, repeated, tag = "1")]
pub proposed_change: ::prost::alloc::vec::Vec<ChangeValue>,
#[prost(uint64, tag = "2")]
pub fee_required: u64,
}
/// An enumeration of change value types.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ChangeValue {
#[prost(oneof = "change_value::Value", tags = "1")]
pub value: ::core::option::Option<change_value::Value>,
}
/// Nested message and enum types in `ChangeValue`.
pub mod change_value {
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Oneof)]
pub enum Value {
#[prost(message, tag = "1")]
SaplingValue(super::SaplingChange),
}
}
/// An object wrapper for memo bytes, to facilitate representing the
/// `change_memo == None` case.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct MemoBytes {
#[prost(bytes = "vec", tag = "1")]
pub value: ::prost::alloc::vec::Vec<u8>,
}
/// The amount and memo for a proposed Sapling change output.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SaplingChange {
#[prost(uint64, tag = "1")]
pub amount: u64,
#[prost(message, optional, tag = "2")]
pub memo: ::core::option::Option<MemoBytes>,
}
/// The fee rule used in constructing a Proposal
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum FeeRule {
/// Protobuf requires that enums have a zero descriminant as the default
/// value. However, we need to require that a known fee rule is selected,
/// and we do not want to fall back to any default, so sending the
/// FeeRuleNotSpecified value will be treated as an error.
NotSpecified = 0,
/// 10000 ZAT
PreZip313 = 1,
/// 1000 ZAT
Zip313 = 2,
/// MAX(10000, 5000 * logical_actions) ZAT
Zip317 = 3,
}
impl FeeRule {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
FeeRule::NotSpecified => "FeeRuleNotSpecified",
FeeRule::PreZip313 => "PreZip313",
FeeRule::Zip313 => "Zip313",
FeeRule::Zip317 => "Zip317",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"FeeRuleNotSpecified" => Some(Self::NotSpecified),
"PreZip313" => Some(Self::PreZip313),
"Zip313" => Some(Self::Zip313),
"Zip317" => Some(Self::Zip317),
_ => None,
}
}
}