build_coinbase api fix and cleanup (#505)

This commit is contained in:
Antioch Peverell 2020-08-10 11:38:03 +01:00 committed by GitHub
parent 3ae8856afe
commit b447dd1f69
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 350 deletions

View file

@ -99,9 +99,9 @@ pub trait ForeignRpc {
},
"key_id": "0300000000000000000000000400000000",
"output": {
"com": "08fe198e525a5937d0c5d01fa354394d2679be6df5d42064a0f7550c332fce3d9d",
"features": 1,
"prf": "9d8488fcb43c9c0f683b9ce62f3c8e047b71f2b4cd94b99a3c9a36aef3bb8361ee17b4489eb5f6d6507250532911acb76f18664604c2ca4215347a5d5d8e417d00ca2d59ec29371286986428b0ec1177fc2e416339ea8542eff8186550ad0d65ffac35d761c38819601d331fd427576e2fff823bbc3faa04f49f5332bd4de46cd4f83d0fd46cdb1dfb87069e95974e4a45e0235db71f5efe5cec83bbb30e152ac50a010ef4e57e33aabbeb894b9114f90bb5c3bb03b009014e358aa3914b1a208eb9d8806fbb679c256d4c1a47b0fce3f1235d58192cb7f615bd7c5dab48486db8962c2a594e69ff70029784a810b4eb76b0516805f3417308cda8acb38b9a3ea061568f0c97f5b46a3beff556dc7ebb58c774f08be472b4b6f603e5f8309c2d1f8d6f52667cb86816b330eca5374148aa898f5bbaf3f23a3ebcdc359ee1e14d73a65596c0ddf51f123234969ac8b557ba9dc53255dd6f5c0d3dd2c035a6d1a1185102612fdca474d018b9f9e81acfa3965d42769f5a303bbaabb78d17e0c026b8be0039c55ad1378c8316101b5206359f89fd1ee239115dde458749a040997be43c039055594cab76f602a0a1ee4f5322f3ab1157342404239adbf8b6786544cd67d9891c2689530e65f2a4b8e52d8551b92ffefb812ffa4a472a10701884151d1fb77d8cdc0b1868cb31b564e98e4c035e0eaa26203b882552c7b69deb0d8ec67cf28d5ec044554f8a91a6cae87eb377d6d906bba6ec94dda24ebfd372727f68334af798b11256d88e17cef7c4fed092128215f992e712ed128db2a9da2f5e8fadea9395bddd294a524dce47f818794c56b03e1253bf0fb9cb8beebc5742e4acf19c24824aa1d41996e839906e24be120a0bdf6800da599ec9ec3d1c4c11571c9f143eadbb554fa3c8c9777994a3f3421d454e4ec54c11b97eea3e4e6ede2d97a2bc"
"commit": "08fe198e525a5937d0c5d01fa354394d2679be6df5d42064a0f7550c332fce3d9d",
"features": "Coinbase",
"proof": "9d8488fcb43c9c0f683b9ce62f3c8e047b71f2b4cd94b99a3c9a36aef3bb8361ee17b4489eb5f6d6507250532911acb76f18664604c2ca4215347a5d5d8e417d00ca2d59ec29371286986428b0ec1177fc2e416339ea8542eff8186550ad0d65ffac35d761c38819601d331fd427576e2fff823bbc3faa04f49f5332bd4de46cd4f83d0fd46cdb1dfb87069e95974e4a45e0235db71f5efe5cec83bbb30e152ac50a010ef4e57e33aabbeb894b9114f90bb5c3bb03b009014e358aa3914b1a208eb9d8806fbb679c256d4c1a47b0fce3f1235d58192cb7f615bd7c5dab48486db8962c2a594e69ff70029784a810b4eb76b0516805f3417308cda8acb38b9a3ea061568f0c97f5b46a3beff556dc7ebb58c774f08be472b4b6f603e5f8309c2d1f8d6f52667cb86816b330eca5374148aa898f5bbaf3f23a3ebcdc359ee1e14d73a65596c0ddf51f123234969ac8b557ba9dc53255dd6f5c0d3dd2c035a6d1a1185102612fdca474d018b9f9e81acfa3965d42769f5a303bbaabb78d17e0c026b8be0039c55ad1378c8316101b5206359f89fd1ee239115dde458749a040997be43c039055594cab76f602a0a1ee4f5322f3ab1157342404239adbf8b6786544cd67d9891c2689530e65f2a4b8e52d8551b92ffefb812ffa4a472a10701884151d1fb77d8cdc0b1868cb31b564e98e4c035e0eaa26203b882552c7b69deb0d8ec67cf28d5ec044554f8a91a6cae87eb377d6d906bba6ec94dda24ebfd372727f68334af798b11256d88e17cef7c4fed092128215f992e712ed128db2a9da2f5e8fadea9395bddd294a524dce47f818794c56b03e1253bf0fb9cb8beebc5742e4acf19c24824aa1d41996e839906e24be120a0bdf6800da599ec9ec3d1c4c11571c9f143eadbb554fa3c8c9777994a3f3421d454e4ec54c11b97eea3e4e6ede2d97a2bc"
}
}
}

View file

@ -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<CbData> 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<OutputFeatures> for OutputFeaturesV4 {
}
}
impl From<Transaction> 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<Input> = 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<SlateV4> for Slate {
fn from(slate: SlateV4) -> Slate {
@ -1230,80 +1128,3 @@ impl From<OutputFeaturesV4> for OutputFeatures {
}
}
}
impl From<TransactionV4> 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,
}

View file

@ -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<RangeProof>,
}
#[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<InputV4>,
/// List of outputs the transaction produces.
#[serde(default = "default_outputs")]
#[serde(skip_serializing_if = "outputs_are_empty")]
pub outs: Vec<OutputV4>,
/// List of kernels that make up this transaction (usually a single kernel).
pub kers: Vec<TxKernelV4>,
}
fn inputs_are_empty(v: &[InputV4]) -> bool {
v.len() == 0
}
fn default_inputs() -> Vec<InputV4> {
vec![]
}
fn outputs_are_empty(v: &[OutputV4]) -> bool {
v.len() == 0
}
fn default_outputs() -> Vec<OutputV4> {
vec![]
}
fn default_range_proof() -> Option<RangeProof> {
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<RangeProof> {
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<Identifier>,
key_id: Option<Identifier>,
}
impl From<CbData> 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,
}