From b447dd1f697ab0184bfaf9264f1758ff53490e84 Mon Sep 17 00:00:00 2001 From: Antioch Peverell Date: Mon, 10 Aug 2020 11:38:03 +0100 Subject: [PATCH] build_coinbase api fix and cleanup (#505) --- api/src/foreign_rpc.rs | 6 +- libwallet/src/slate.rs | 187 +---------------------- libwallet/src/slate_versions/v4.rs | 233 +++++++++-------------------- 3 files changed, 76 insertions(+), 350 deletions(-) diff --git a/api/src/foreign_rpc.rs b/api/src/foreign_rpc.rs index 069633ba..7e1c07b6 100644 --- a/api/src/foreign_rpc.rs +++ b/api/src/foreign_rpc.rs @@ -99,9 +99,9 @@ pub trait ForeignRpc { }, "key_id": "0300000000000000000000000400000000", "output": { - "com": "08fe198e525a5937d0c5d01fa354394d2679be6df5d42064a0f7550c332fce3d9d", - "features": 1, - "prf": "9d8488fcb43c9c0f683b9ce62f3c8e047b71f2b4cd94b99a3c9a36aef3bb8361ee17b4489eb5f6d6507250532911acb76f18664604c2ca4215347a5d5d8e417d00ca2d59ec29371286986428b0ec1177fc2e416339ea8542eff8186550ad0d65ffac35d761c38819601d331fd427576e2fff823bbc3faa04f49f5332bd4de46cd4f83d0fd46cdb1dfb87069e95974e4a45e0235db71f5efe5cec83bbb30e152ac50a010ef4e57e33aabbeb894b9114f90bb5c3bb03b009014e358aa3914b1a208eb9d8806fbb679c256d4c1a47b0fce3f1235d58192cb7f615bd7c5dab48486db8962c2a594e69ff70029784a810b4eb76b0516805f3417308cda8acb38b9a3ea061568f0c97f5b46a3beff556dc7ebb58c774f08be472b4b6f603e5f8309c2d1f8d6f52667cb86816b330eca5374148aa898f5bbaf3f23a3ebcdc359ee1e14d73a65596c0ddf51f123234969ac8b557ba9dc53255dd6f5c0d3dd2c035a6d1a1185102612fdca474d018b9f9e81acfa3965d42769f5a303bbaabb78d17e0c026b8be0039c55ad1378c8316101b5206359f89fd1ee239115dde458749a040997be43c039055594cab76f602a0a1ee4f5322f3ab1157342404239adbf8b6786544cd67d9891c2689530e65f2a4b8e52d8551b92ffefb812ffa4a472a10701884151d1fb77d8cdc0b1868cb31b564e98e4c035e0eaa26203b882552c7b69deb0d8ec67cf28d5ec044554f8a91a6cae87eb377d6d906bba6ec94dda24ebfd372727f68334af798b11256d88e17cef7c4fed092128215f992e712ed128db2a9da2f5e8fadea9395bddd294a524dce47f818794c56b03e1253bf0fb9cb8beebc5742e4acf19c24824aa1d41996e839906e24be120a0bdf6800da599ec9ec3d1c4c11571c9f143eadbb554fa3c8c9777994a3f3421d454e4ec54c11b97eea3e4e6ede2d97a2bc" + "commit": "08fe198e525a5937d0c5d01fa354394d2679be6df5d42064a0f7550c332fce3d9d", + "features": "Coinbase", + "proof": "9d8488fcb43c9c0f683b9ce62f3c8e047b71f2b4cd94b99a3c9a36aef3bb8361ee17b4489eb5f6d6507250532911acb76f18664604c2ca4215347a5d5d8e417d00ca2d59ec29371286986428b0ec1177fc2e416339ea8542eff8186550ad0d65ffac35d761c38819601d331fd427576e2fff823bbc3faa04f49f5332bd4de46cd4f83d0fd46cdb1dfb87069e95974e4a45e0235db71f5efe5cec83bbb30e152ac50a010ef4e57e33aabbeb894b9114f90bb5c3bb03b009014e358aa3914b1a208eb9d8806fbb679c256d4c1a47b0fce3f1235d58192cb7f615bd7c5dab48486db8962c2a594e69ff70029784a810b4eb76b0516805f3417308cda8acb38b9a3ea061568f0c97f5b46a3beff556dc7ebb58c774f08be472b4b6f603e5f8309c2d1f8d6f52667cb86816b330eca5374148aa898f5bbaf3f23a3ebcdc359ee1e14d73a65596c0ddf51f123234969ac8b557ba9dc53255dd6f5c0d3dd2c035a6d1a1185102612fdca474d018b9f9e81acfa3965d42769f5a303bbaabb78d17e0c026b8be0039c55ad1378c8316101b5206359f89fd1ee239115dde458749a040997be43c039055594cab76f602a0a1ee4f5322f3ab1157342404239adbf8b6786544cd67d9891c2689530e65f2a4b8e52d8551b92ffefb812ffa4a472a10701884151d1fb77d8cdc0b1868cb31b564e98e4c035e0eaa26203b882552c7b69deb0d8ec67cf28d5ec044554f8a91a6cae87eb377d6d906bba6ec94dda24ebfd372727f68334af798b11256d88e17cef7c4fed092128215f992e712ed128db2a9da2f5e8fadea9395bddd294a524dce47f818794c56b03e1253bf0fb9cb8beebc5742e4acf19c24824aa1d41996e839906e24be120a0bdf6800da599ec9ec3d1c4c11571c9f143eadbb554fa3c8c9777994a3f3421d454e4ec54c11b97eea3e4e6ede2d97a2bc" } } } diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index 061f0edc..e8cc3b7c 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -18,8 +18,8 @@ use crate::error::{Error, ErrorKind}; use crate::grin_core::core::amount_to_hr_string; use crate::grin_core::core::transaction::{ - Input, KernelFeatures, NRDRelativeHeight, Output, OutputFeatures, Transaction, TransactionBody, - TxKernel, Weighting, + Input, KernelFeatures, NRDRelativeHeight, Output, OutputFeatures, Transaction, TxKernel, + Weighting, }; use crate::grin_core::core::verifier_cache::LruVerifierCache; use crate::grin_core::libtx::{aggsig, build, proof::ProofBuild, tx_fee}; @@ -40,13 +40,11 @@ use std::sync::Arc; use uuid::Uuid; use crate::slate_versions::v4::{ - CoinbaseV4, CommitsV4, InputV4, KernelFeaturesArgsV4, OutputFeaturesV4, OutputV4, - ParticipantDataV4, PaymentInfoV4, SlateStateV4, SlateV4, TransactionBodyV4, TransactionV4, - TxKernelV4, VersionCompatInfoV4, + CommitsV4, KernelFeaturesArgsV4, OutputFeaturesV4, ParticipantDataV4, PaymentInfoV4, + SlateStateV4, SlateV4, VersionCompatInfoV4, }; use crate::slate_versions::VersionedSlate; use crate::slate_versions::{CURRENT_SLATE_VERSION, GRIN_BLOCK_HEADER_VERSION}; -use crate::types::CbData; #[derive(Debug, Clone)] pub struct PaymentInfo { @@ -716,18 +714,6 @@ impl Serialize for Slate { v4.serialize(serializer) } } - -// Coinbase data to versioned. -impl From for CoinbaseV4 { - fn from(cb: CbData) -> CoinbaseV4 { - CoinbaseV4 { - output: OutputV4::from(&cb.output), - kernel: TxKernelV4::from(&cb.kernel), - key_id: cb.key_id, - } - } -} - // Current slate version to versioned conversions // Slate to versioned @@ -945,94 +931,6 @@ impl From for OutputFeaturesV4 { } } -impl From for TransactionV4 { - fn from(tx: Transaction) -> TransactionV4 { - let Transaction { offset, body } = tx; - let body = TransactionBodyV4::from(&body); - TransactionV4 { offset, body } - } -} - -impl From<&Transaction> for TransactionV4 { - fn from(tx: &Transaction) -> TransactionV4 { - let Transaction { offset, body } = tx; - let offset = offset.clone(); - let body = TransactionBodyV4::from(body); - TransactionV4 { offset, body } - } -} - -impl From<&TransactionBody> for TransactionBodyV4 { - fn from(body: &TransactionBody) -> TransactionBodyV4 { - // TODO - input features will soon be deprecated. - // We should treat inputs here as vec of commitments. - let inputs: Vec = body.inputs().into(); - let outputs = body.outputs(); - let kernels = body.kernels(); - - let inputs = map_vec!(inputs, |inp| InputV4::from(inp)); - let outputs = map_vec!(outputs, |out| OutputV4::from(out)); - let kernels = map_vec!(kernels, |kern| TxKernelV4::from(kern)); - TransactionBodyV4 { - ins: inputs, - outs: outputs, - kers: kernels, - } - } -} - -impl From<&Input> for InputV4 { - fn from(input: &Input) -> InputV4 { - let Input { features, commit } = *input; - InputV4 { - features: features.into(), - commit, - } - } -} - -impl From<&Output> for OutputV4 { - fn from(output: &Output) -> OutputV4 { - let Output { - features, - commit, - proof, - } = *output; - OutputV4 { - features: features.into(), - com: commit, - prf: proof, - } - } -} - -impl From<&TxKernel> for TxKernelV4 { - fn from(kernel: &TxKernel) -> TxKernelV4 { - let (features, fee, lock_height) = match kernel.features { - KernelFeatures::Plain { fee } => (CompatKernelFeatures::Plain, fee, 0), - KernelFeatures::Coinbase => (CompatKernelFeatures::Coinbase, 0, 0), - KernelFeatures::HeightLocked { fee, lock_height } => { - (CompatKernelFeatures::HeightLocked, fee, lock_height) - } - KernelFeatures::NoRecentDuplicate { - fee, - relative_height, - } => ( - CompatKernelFeatures::NoRecentDuplicate, - fee, - relative_height.into(), - ), - }; - TxKernelV4 { - features, - fee, - lock_height, - excess: kernel.excess, - excess_sig: kernel.excess_sig, - } - } -} - // Versioned to current slate impl From for Slate { fn from(slate: SlateV4) -> Slate { @@ -1230,80 +1128,3 @@ impl From for OutputFeatures { } } } - -impl From for Transaction { - fn from(tx: TransactionV4) -> Transaction { - let TransactionV4 { offset, body } = tx; - let body = TransactionBody::from(&body); - Transaction { offset, body } - } -} - -impl From<&TransactionBodyV4> for TransactionBody { - fn from(body: &TransactionBodyV4) -> TransactionBody { - let TransactionBodyV4 { ins, outs, kers } = body; - - let inputs = map_vec!(ins, |inp| Input::from(inp)); - let outputs = map_vec!(outs, |out| Output::from(out)); - let kernels = map_vec!(kers, |kern| TxKernel::from(kern)); - TransactionBody { - inputs: inputs.into(), - outputs, - kernels, - } - } -} - -impl From<&InputV4> for Input { - fn from(input: &InputV4) -> Input { - let InputV4 { features, commit } = *input; - Input { - features: features.into(), - commit, - } - } -} - -impl From<&OutputV4> for Output { - fn from(output: &OutputV4) -> Output { - let OutputV4 { - features, - com: commit, - prf: proof, - } = *output; - Output { - features: features.into(), - commit, - proof, - } - } -} - -impl From<&TxKernelV4> for TxKernel { - fn from(kernel: &TxKernelV4) -> TxKernel { - let (fee, lock_height) = (kernel.fee, kernel.lock_height); - let features = match kernel.features { - CompatKernelFeatures::Plain => KernelFeatures::Plain { fee }, - CompatKernelFeatures::Coinbase => KernelFeatures::Coinbase, - CompatKernelFeatures::HeightLocked => KernelFeatures::HeightLocked { fee, lock_height }, - CompatKernelFeatures::NoRecentDuplicate => KernelFeatures::NoRecentDuplicate { - fee, - relative_height: NRDRelativeHeight::new(lock_height) - .expect("a valid NRD relative height"), - }, - }; - TxKernel { - features, - excess: kernel.excess, - excess_sig: kernel.excess_sig, - } - } -} - -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub enum CompatKernelFeatures { - Plain, - Coinbase, - HeightLocked, - NoRecentDuplicate, -} diff --git a/libwallet/src/slate_versions/v4.rs b/libwallet/src/slate_versions/v4.rs index fcf48d92..2564547d 100644 --- a/libwallet/src/slate_versions/v4.rs +++ b/libwallet/src/slate_versions/v4.rs @@ -53,14 +53,14 @@ //! * The `receiver_signature` field is renamed to `rsig` //! * `rsig` may be omitted if it has not yet been filled out +use crate::grin_core::core::{Output, TxKernel}; use crate::grin_core::libtx::secp_ser; use crate::grin_keychain::{BlindingFactor, Identifier}; use crate::grin_util::secp; use crate::grin_util::secp::key::PublicKey; use crate::grin_util::secp::pedersen::{Commitment, RangeProof}; use crate::grin_util::secp::Signature; -use crate::slate::CompatKernelFeatures; -use crate::slate_versions::ser; +use crate::{slate_versions::ser, CbData}; use ed25519_dalek::PublicKey as DalekPublicKey; use ed25519_dalek::Signature as DalekSignature; use uuid::Uuid; @@ -252,103 +252,6 @@ pub struct CommitsV4 { pub p: Option, } -#[derive(Serialize, Deserialize, Copy, Debug, Clone, PartialEq, Eq)] -pub struct OutputFeaturesV4(pub u8); - -/// A transaction -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct TransactionV4 { - /// The kernel "offset" k2 - /// excess is k1G after splitting the key k = k1 + k2 - #[serde( - serialize_with = "secp_ser::as_hex", - deserialize_with = "secp_ser::blind_from_hex" - )] - #[serde(default = "default_blinding_factor")] - #[serde(skip_serializing_if = "blinding_factor_is_zero")] - pub offset: BlindingFactor, - /// The transaction body - inputs/outputs/kernels - pub body: TransactionBodyV4, -} - -fn default_blinding_factor() -> BlindingFactor { - BlindingFactor::zero() -} - -fn blinding_factor_is_zero(bf: &BlindingFactor) -> bool { - *bf == BlindingFactor::zero() -} - -/// TransactionBody is a common abstraction for transaction and block -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct TransactionBodyV4 { - /// List of inputs spent by the transaction. - #[serde(default = "default_inputs")] - #[serde(skip_serializing_if = "inputs_are_empty")] - pub ins: Vec, - /// List of outputs the transaction produces. - #[serde(default = "default_outputs")] - #[serde(skip_serializing_if = "outputs_are_empty")] - pub outs: Vec, - /// List of kernels that make up this transaction (usually a single kernel). - pub kers: Vec, -} - -fn inputs_are_empty(v: &[InputV4]) -> bool { - v.len() == 0 -} - -fn default_inputs() -> Vec { - vec![] -} - -fn outputs_are_empty(v: &[OutputV4]) -> bool { - v.len() == 0 -} - -fn default_outputs() -> Vec { - vec![] -} - -fn default_range_proof() -> Option { - None -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct InputV4 { - /// The features of the output being spent. - /// We will check maturity for coinbase output. - #[serde(default = "default_output_feature")] - #[serde(skip_serializing_if = "output_feature_is_plain")] - pub features: OutputFeaturesV4, - /// The commit referencing the output being spent. - #[serde( - serialize_with = "secp_ser::as_hex", - deserialize_with = "secp_ser::commitment_from_hex" - )] - pub commit: Commitment, -} - -#[derive(Debug, Copy, Clone, Serialize, Deserialize)] -pub struct OutputV4 { - /// Options for an output's structure or use - #[serde(default = "default_output_feature")] - #[serde(skip_serializing_if = "output_feature_is_plain")] - pub features: OutputFeaturesV4, - /// The homomorphic commitment representing the output amount - #[serde( - serialize_with = "secp_ser::as_hex", - deserialize_with = "secp_ser::commitment_from_hex" - )] - pub com: Commitment, - /// A proof that the commitment is in the right range - #[serde( - serialize_with = "secp_ser::as_hex", - deserialize_with = "secp_ser::rangeproof_from_hex" - )] - pub prf: RangeProof, -} - fn default_output_feature() -> OutputFeaturesV4 { OutputFeaturesV4(0) } @@ -357,68 +260,8 @@ fn output_feature_is_plain(o: &OutputFeaturesV4) -> bool { o.0 == 0 } -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct TxKernelV4 { - /// Options for a kernel's structure or use - #[serde(default = "default_kernel_feature")] - #[serde(skip_serializing_if = "kernel_feature_is_plain")] - pub features: CompatKernelFeatures, - /// Fee originally included in the transaction this proof is for. - #[serde(with = "secp_ser::string_or_u64")] - #[serde(default = "default_u64")] - #[serde(skip_serializing_if = "u64_is_blank")] - pub fee: u64, - /// This kernel is not valid earlier than lock_height blocks - /// The max lock_height of all *inputs* to this transaction - #[serde(with = "secp_ser::string_or_u64")] - #[serde(default = "default_u64")] - #[serde(skip_serializing_if = "u64_is_blank")] - pub lock_height: u64, - /// Remainder of the sum of all transaction commitments. If the transaction - /// is well formed, amounts components should sum to zero and the excess - /// is hence a valid public key. - #[serde( - serialize_with = "secp_ser::as_hex", - deserialize_with = "secp_ser::commitment_from_hex" - )] - #[serde(default = "default_commitment")] - #[serde(skip_serializing_if = "commitment_is_blank")] - pub excess: Commitment, - /// The signature proving the excess is a valid public key, which signs - /// the transaction fee. - #[serde(with = "secp_ser::sig_serde")] - #[serde(default = "default_sig")] - #[serde(skip_serializing_if = "sig_is_blank")] - pub excess_sig: secp::Signature, -} - -fn default_kernel_feature() -> CompatKernelFeatures { - CompatKernelFeatures::Plain -} - -fn kernel_feature_is_plain(k: &CompatKernelFeatures) -> bool { - match k { - CompatKernelFeatures::Plain => true, - _ => false, - } -} - -fn default_commitment() -> Commitment { - Commitment::from_vec([0u8; 1].to_vec()) -} - -fn commitment_is_blank(c: &Commitment) -> bool { - for b in c.0.iter() { - if *b != 0 { - return false; - } - } - true -} - -fn default_sig() -> secp::Signature { - Signature::from_raw_data(&[0; 64]).unwrap() -} +#[derive(Serialize, Deserialize, Copy, Debug, Clone, PartialEq, Eq)] +pub struct OutputFeaturesV4(pub u8); pub fn sig_is_blank(s: &secp::Signature) -> bool { for b in s.to_raw_data().iter() { @@ -429,6 +272,10 @@ pub fn sig_is_blank(s: &secp::Signature) -> bool { true } +fn default_range_proof() -> Option { + None +} + fn default_u64() -> u64 { 0 } @@ -448,9 +295,67 @@ fn u8_is_blank(u: &u8) -> bool { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct CoinbaseV4 { /// Output - pub output: OutputV4, + output: CbOutputV4, /// Kernel - pub kernel: TxKernelV4, + kernel: CbKernelV4, /// Key Id - pub key_id: Option, + key_id: Option, +} + +impl From for CoinbaseV4 { + fn from(cb: CbData) -> CoinbaseV4 { + CoinbaseV4 { + output: CbOutputV4::from(&cb.output), + kernel: CbKernelV4::from(&cb.kernel), + key_id: cb.key_id, + } + } +} + +impl From<&Output> for CbOutputV4 { + fn from(output: &Output) -> CbOutputV4 { + CbOutputV4 { + features: CbOutputFeatures::Coinbase, + commit: output.commit, + proof: output.proof, + } + } +} + +impl From<&TxKernel> for CbKernelV4 { + fn from(kernel: &TxKernel) -> CbKernelV4 { + CbKernelV4 { + features: CbKernelFeatures::Coinbase, + excess: kernel.excess, + excess_sig: kernel.excess_sig, + } + } +} + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +enum CbOutputFeatures { + Coinbase, +} + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +enum CbKernelFeatures { + Coinbase, +} + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +struct CbOutputV4 { + features: CbOutputFeatures, + #[serde(serialize_with = "secp_ser::as_hex")] + commit: Commitment, + #[serde(serialize_with = "secp_ser::as_hex")] + proof: RangeProof, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +struct CbKernelV4 { + features: CbKernelFeatures, + #[serde(serialize_with = "secp_ser::as_hex")] + excess: Commitment, + #[serde(with = "secp_ser::sig_serde")] + excess_sig: secp::Signature, }