mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-10-17 15:21:39 +02:00
share slate types
This commit is contained in:
+16
-128
@@ -42,8 +42,8 @@ use crate::slate_versions::v4::{
|
|||||||
SlateStateV4, SlateV4, VersionCompatInfoV4,
|
SlateStateV4, SlateV4, VersionCompatInfoV4,
|
||||||
};
|
};
|
||||||
use crate::slate_versions::v5::{
|
use crate::slate_versions::v5::{
|
||||||
CommitsV5, KernelFeaturesArgsV5, OutputFeaturesV5, ParticipantDataV5, PaymentInfoV5,
|
KernelFeaturesArgsV5, ParticipantDataV5, PaymentInfoV5, SlateStateV5, SlateV5,
|
||||||
SlateStateV5, SlateV5, VersionCompatInfoV5,
|
VersionCompatInfoV5,
|
||||||
};
|
};
|
||||||
use crate::slate_versions::VersionedSlate;
|
use crate::slate_versions::VersionedSlate;
|
||||||
use crate::slate_versions::{CURRENT_SLATE_VERSION, GRIN_BLOCK_HEADER_VERSION};
|
use crate::slate_versions::{CURRENT_SLATE_VERSION, GRIN_BLOCK_HEADER_VERSION};
|
||||||
@@ -1032,72 +1032,6 @@ impl From<&Slate> for SlateV5 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Slate> for Option<Vec<CommitsV5>> {
|
|
||||||
fn from(slate: &Slate) -> Self {
|
|
||||||
slate_commitments(slate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn slate_commitments<C>(slate: &Slate) -> Option<Vec<C>>
|
|
||||||
where
|
|
||||||
C: for<'a> From<&'a Input> + for<'a> From<&'a Output>,
|
|
||||||
{
|
|
||||||
let tx = slate.tx.as_ref()?;
|
|
||||||
let mut commitments = vec![];
|
|
||||||
match tx.inputs() {
|
|
||||||
Inputs::CommitOnly(_) => panic!("commit only inputs unsupported"),
|
|
||||||
Inputs::FeaturesAndCommit(ref inputs) => {
|
|
||||||
for input in inputs {
|
|
||||||
commitments.push(input.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for output in tx.outputs() {
|
|
||||||
commitments.push(output.into());
|
|
||||||
}
|
|
||||||
Some(commitments)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&ParticipantData> for ParticipantDataV5 {
|
|
||||||
fn from(data: &ParticipantData) -> ParticipantDataV5 {
|
|
||||||
let ParticipantData {
|
|
||||||
public_blind_excess,
|
|
||||||
public_nonce,
|
|
||||||
part_sig,
|
|
||||||
} = data;
|
|
||||||
let public_blind_excess = *public_blind_excess;
|
|
||||||
let public_nonce = *public_nonce;
|
|
||||||
let part_sig = *part_sig;
|
|
||||||
ParticipantDataV5 {
|
|
||||||
xs: public_blind_excess,
|
|
||||||
nonce: public_nonce,
|
|
||||||
part: part_sig,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&SlateState> for SlateStateV5 {
|
|
||||||
fn from(data: &SlateState) -> SlateStateV5 {
|
|
||||||
match data {
|
|
||||||
SlateState::Unknown => SlateStateV5::Unknown,
|
|
||||||
SlateState::Standard1 => SlateStateV5::Standard1,
|
|
||||||
SlateState::Standard2 => SlateStateV5::Standard2,
|
|
||||||
SlateState::Standard3 => SlateStateV5::Standard3,
|
|
||||||
SlateState::Invoice1 => SlateStateV5::Invoice1,
|
|
||||||
SlateState::Invoice2 => SlateStateV5::Invoice2,
|
|
||||||
SlateState::Invoice3 => SlateStateV5::Invoice3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&KernelFeaturesArgs> for KernelFeaturesArgsV5 {
|
|
||||||
fn from(data: &KernelFeaturesArgs) -> KernelFeaturesArgsV5 {
|
|
||||||
let KernelFeaturesArgs { lock_height } = data;
|
|
||||||
let lock_hgt = *lock_height;
|
|
||||||
KernelFeaturesArgsV5 { lock_hgt }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&VersionCompatInfo> for VersionCompatInfoV5 {
|
impl From<&VersionCompatInfo> for VersionCompatInfoV5 {
|
||||||
fn from(data: &VersionCompatInfo) -> VersionCompatInfoV5 {
|
fn from(data: &VersionCompatInfo) -> VersionCompatInfoV5 {
|
||||||
let VersionCompatInfo {
|
let VersionCompatInfo {
|
||||||
@@ -1141,16 +1075,6 @@ impl From<&PaymentInfo> for PaymentInfoV5 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<OutputFeatures> for OutputFeaturesV5 {
|
|
||||||
fn from(of: OutputFeatures) -> OutputFeaturesV5 {
|
|
||||||
let index = match of {
|
|
||||||
OutputFeatures::Plain => 0,
|
|
||||||
OutputFeatures::Coinbase => 1,
|
|
||||||
};
|
|
||||||
OutputFeaturesV5(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///// V5
|
///// V5
|
||||||
impl From<SlateV5> for Slate {
|
impl From<SlateV5> for Slate {
|
||||||
fn from(slate: SlateV5) -> Slate {
|
fn from(slate: SlateV5) -> Slate {
|
||||||
@@ -1273,46 +1197,6 @@ impl From<&SlateV5> for Option<Transaction> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&ParticipantDataV5> for ParticipantData {
|
|
||||||
fn from(data: &ParticipantDataV5) -> ParticipantData {
|
|
||||||
let ParticipantDataV5 {
|
|
||||||
xs: public_blind_excess,
|
|
||||||
nonce: public_nonce,
|
|
||||||
part: part_sig,
|
|
||||||
} = data;
|
|
||||||
let public_blind_excess = *public_blind_excess;
|
|
||||||
let public_nonce = *public_nonce;
|
|
||||||
let part_sig = *part_sig;
|
|
||||||
ParticipantData {
|
|
||||||
public_blind_excess,
|
|
||||||
public_nonce,
|
|
||||||
part_sig,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&KernelFeaturesArgsV5> for KernelFeaturesArgs {
|
|
||||||
fn from(data: &KernelFeaturesArgsV5) -> KernelFeaturesArgs {
|
|
||||||
let KernelFeaturesArgsV5 { lock_hgt } = data;
|
|
||||||
let lock_height = *lock_hgt;
|
|
||||||
KernelFeaturesArgs { lock_height }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&SlateStateV5> for SlateState {
|
|
||||||
fn from(data: &SlateStateV5) -> SlateState {
|
|
||||||
match data {
|
|
||||||
SlateStateV5::Unknown => SlateState::Unknown,
|
|
||||||
SlateStateV5::Standard1 => SlateState::Standard1,
|
|
||||||
SlateStateV5::Standard2 => SlateState::Standard2,
|
|
||||||
SlateStateV5::Standard3 => SlateState::Standard3,
|
|
||||||
SlateStateV5::Invoice1 => SlateState::Invoice1,
|
|
||||||
SlateStateV5::Invoice2 => SlateState::Invoice2,
|
|
||||||
SlateStateV5::Invoice3 => SlateState::Invoice3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&VersionCompatInfoV5> for VersionCompatInfo {
|
impl From<&VersionCompatInfoV5> for VersionCompatInfo {
|
||||||
fn from(data: &VersionCompatInfoV5) -> VersionCompatInfo {
|
fn from(data: &VersionCompatInfoV5) -> VersionCompatInfo {
|
||||||
let VersionCompatInfoV5 {
|
let VersionCompatInfoV5 {
|
||||||
@@ -1355,15 +1239,6 @@ impl From<&PaymentInfoV5> for PaymentInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<OutputFeaturesV5> for OutputFeatures {
|
|
||||||
fn from(of: OutputFeaturesV5) -> OutputFeatures {
|
|
||||||
match of.0 {
|
|
||||||
1 => OutputFeatures::Coinbase,
|
|
||||||
0 | _ => OutputFeatures::Plain,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////// V4
|
///////// V4
|
||||||
impl TryFrom<Slate> for SlateV4 {
|
impl TryFrom<Slate> for SlateV4 {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
@@ -1430,7 +1305,20 @@ impl TryFrom<&Slate> for SlateV4 {
|
|||||||
|
|
||||||
impl From<&Slate> for Option<Vec<CommitsV4>> {
|
impl From<&Slate> for Option<Vec<CommitsV4>> {
|
||||||
fn from(slate: &Slate) -> Self {
|
fn from(slate: &Slate) -> Self {
|
||||||
slate_commitments(slate)
|
let tx = slate.tx.as_ref()?;
|
||||||
|
let mut commitments = vec![];
|
||||||
|
match tx.inputs() {
|
||||||
|
Inputs::CommitOnly(_) => panic!("commit only inputs unsupported"),
|
||||||
|
Inputs::FeaturesAndCommit(ref inputs) => {
|
||||||
|
for input in inputs {
|
||||||
|
commitments.push(input.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for output in tx.outputs() {
|
||||||
|
commitments.push(output.into());
|
||||||
|
}
|
||||||
|
Some(commitments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,207 @@
|
|||||||
|
// Copyright 2026 The Grin Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//! Wire types shared by V4 and V5 slates
|
||||||
|
|
||||||
|
use crate::grin_core::core::{Input, Output, TxKernel};
|
||||||
|
use crate::grin_core::libtx::secp_ser;
|
||||||
|
use crate::grin_keychain::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_versions::ser, CbData};
|
||||||
|
|
||||||
|
/// Slate state definition
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub enum SlateState {
|
||||||
|
/// Unknown, coming from earlier versions of the slate
|
||||||
|
Unknown,
|
||||||
|
/// Standard flow, freshly init
|
||||||
|
Standard1,
|
||||||
|
/// Standard flow, return journey
|
||||||
|
Standard2,
|
||||||
|
/// Standard flow, ready for transaction posting
|
||||||
|
Standard3,
|
||||||
|
/// Invoice flow, freshly init
|
||||||
|
Invoice1,
|
||||||
|
/// Invoice flow, return journey
|
||||||
|
Invoice2,
|
||||||
|
/// Invoice flow, ready for tranasction posting
|
||||||
|
Invoice3,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
|
/// Kernel features arguments definition
|
||||||
|
pub struct KernelFeaturesArgs {
|
||||||
|
/// Lock height, for HeightLocked
|
||||||
|
pub lock_hgt: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Participant keys and optional partial signature
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct ParticipantData {
|
||||||
|
/// Public key corresponding to private blinding factor
|
||||||
|
#[serde(with = "secp_ser::pubkey_serde")]
|
||||||
|
pub xs: PublicKey,
|
||||||
|
/// Public key corresponding to private nonce
|
||||||
|
#[serde(with = "secp_ser::pubkey_serde")]
|
||||||
|
pub nonce: PublicKey,
|
||||||
|
/// Public partial signature
|
||||||
|
#[serde(default = "default_part_sig_none")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[serde(with = "secp_ser::option_sig_serde")]
|
||||||
|
pub part: Option<Signature>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_part_sig_none() -> Option<Signature> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Input commitment or output with its range proof
|
||||||
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Commits {
|
||||||
|
/// Options for an output's structure or use
|
||||||
|
#[serde(default = "default_output_feature")]
|
||||||
|
#[serde(skip_serializing_if = "output_feature_is_plain")]
|
||||||
|
pub f: OutputFeatures,
|
||||||
|
/// The homomorphic commitment representing the output amount
|
||||||
|
#[serde(
|
||||||
|
serialize_with = "secp_ser::as_hex",
|
||||||
|
deserialize_with = "secp_ser::commitment_from_hex"
|
||||||
|
)]
|
||||||
|
pub c: Commitment,
|
||||||
|
/// A proof that the commitment is in the right range
|
||||||
|
/// Only applies for transaction outputs
|
||||||
|
#[serde(with = "ser::option_rangeproof_hex")]
|
||||||
|
#[serde(default = "default_range_proof")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub p: Option<RangeProof>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Output> for Commits {
|
||||||
|
fn from(out: &Output) -> Commits {
|
||||||
|
Commits {
|
||||||
|
f: out.features().into(),
|
||||||
|
c: out.commitment(),
|
||||||
|
p: Some(out.proof()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will need to be reworked once we no longer support input features with "commit only" inputs.
|
||||||
|
impl From<&Input> for Commits {
|
||||||
|
fn from(input: &Input) -> Commits {
|
||||||
|
Commits {
|
||||||
|
f: input.features.into(),
|
||||||
|
c: input.commitment(),
|
||||||
|
p: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_output_feature() -> OutputFeatures {
|
||||||
|
OutputFeatures(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_feature_is_plain(o: &OutputFeatures) -> bool {
|
||||||
|
o.0 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Output feature byte
|
||||||
|
#[derive(Serialize, Deserialize, Copy, Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct OutputFeatures(pub u8);
|
||||||
|
|
||||||
|
/// Whether all signature bytes are zero
|
||||||
|
pub fn sig_is_blank(s: &secp::Signature) -> bool {
|
||||||
|
for b in s.to_raw_data().iter() {
|
||||||
|
if *b != 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_range_proof() -> Option<RangeProof> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A mining node requests new coinbase via the foreign api every time a new candidate block is built.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct Coinbase {
|
||||||
|
/// Output
|
||||||
|
output: CbOutput,
|
||||||
|
/// Kernel
|
||||||
|
kernel: CbKernel,
|
||||||
|
/// Key Id
|
||||||
|
key_id: Option<Identifier>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CbData> for Coinbase {
|
||||||
|
fn from(cb: CbData) -> Coinbase {
|
||||||
|
Coinbase {
|
||||||
|
output: CbOutput::from(&cb.output),
|
||||||
|
kernel: CbKernel::from(&cb.kernel),
|
||||||
|
key_id: cb.key_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Output> for CbOutput {
|
||||||
|
fn from(output: &Output) -> CbOutput {
|
||||||
|
CbOutput {
|
||||||
|
features: CbOutputFeatures::Coinbase,
|
||||||
|
commit: output.commitment(),
|
||||||
|
proof: output.proof(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&TxKernel> for CbKernel {
|
||||||
|
fn from(kernel: &TxKernel) -> CbKernel {
|
||||||
|
CbKernel {
|
||||||
|
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 CbOutput {
|
||||||
|
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 CbKernel {
|
||||||
|
features: CbKernelFeatures,
|
||||||
|
#[serde(serialize_with = "secp_ser::as_hex")]
|
||||||
|
excess: Commitment,
|
||||||
|
#[serde(with = "secp_ser::sig_serde")]
|
||||||
|
excess_sig: secp::Signature,
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ use crate::types::CbData;
|
|||||||
use crate::Error;
|
use crate::Error;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
mod common;
|
||||||
pub mod ser;
|
pub mod ser;
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
@@ -605,6 +606,40 @@ pub mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slate_states() {
|
||||||
|
use crate::grin_core::ser::{deserialize_default, serialize_default};
|
||||||
|
use crate::slate::SlateState;
|
||||||
|
use crate::slate_versions::v5::SlateStateV5;
|
||||||
|
|
||||||
|
for (state, label, byte) in [
|
||||||
|
(SlateState::Unknown, "NA", 0),
|
||||||
|
(SlateState::Standard1, "S1", 1),
|
||||||
|
(SlateState::Standard2, "S2", 2),
|
||||||
|
(SlateState::Standard3, "S3", 3),
|
||||||
|
(SlateState::Invoice1, "I1", 4),
|
||||||
|
(SlateState::Invoice2, "I2", 5),
|
||||||
|
(SlateState::Invoice3, "I3", 6),
|
||||||
|
] {
|
||||||
|
let mut slate = Slate::blank(2, false);
|
||||||
|
slate.state = state;
|
||||||
|
for version in [SlateVersion::V4, SlateVersion::V5] {
|
||||||
|
let versioned = VersionedSlate::into_version(slate.clone(), version).unwrap();
|
||||||
|
let json = serde_json::to_value(&versioned).unwrap();
|
||||||
|
assert_eq!(json["sta"], label);
|
||||||
|
let recovered: Slate = serde_json::from_value::<VersionedSlate>(json)
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
|
assert_eq!(recovered.state, slate.state);
|
||||||
|
}
|
||||||
|
let mut bytes = vec![];
|
||||||
|
serialize_default(&mut bytes, &SlateStateV5::from(&slate.state)).unwrap();
|
||||||
|
assert_eq!(bytes, vec![byte]);
|
||||||
|
let recovered: SlateStateV5 = deserialize_default(&mut &bytes[..]).unwrap();
|
||||||
|
assert_eq!(SlateState::from(&recovered), slate.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn slate_version_numbers() {
|
fn slate_version_numbers() {
|
||||||
for (number, version) in [(4, SlateVersion::V4), (5, SlateVersion::V5)] {
|
for (number, version) in [(4, SlateVersion::V4), (5, SlateVersion::V5)] {
|
||||||
|
|||||||
@@ -682,50 +682,7 @@ pub mod slate_state_v4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes slates 'state' field - V5
|
pub use slate_state_v4 as slate_state_v5;
|
||||||
pub mod slate_state_v5 {
|
|
||||||
use serde::de::Error;
|
|
||||||
use serde::{Deserialize, Deserializer, Serializer};
|
|
||||||
|
|
||||||
use crate::slate_versions::v5::SlateStateV5;
|
|
||||||
|
|
||||||
///
|
|
||||||
pub fn serialize<S>(st: &SlateStateV5, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
let label = match st {
|
|
||||||
SlateStateV5::Unknown => "NA",
|
|
||||||
SlateStateV5::Standard1 => "S1",
|
|
||||||
SlateStateV5::Standard2 => "S2",
|
|
||||||
SlateStateV5::Standard3 => "S3",
|
|
||||||
SlateStateV5::Invoice1 => "I1",
|
|
||||||
SlateStateV5::Invoice2 => "I2",
|
|
||||||
SlateStateV5::Invoice3 => "I3",
|
|
||||||
};
|
|
||||||
serializer.serialize_str(label)
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<SlateStateV5, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
String::deserialize(deserializer).and_then(|s| {
|
|
||||||
let retval = match s.as_str() {
|
|
||||||
"NA" => SlateStateV5::Unknown,
|
|
||||||
"S1" => SlateStateV5::Standard1,
|
|
||||||
"S2" => SlateStateV5::Standard2,
|
|
||||||
"S3" => SlateStateV5::Standard3,
|
|
||||||
"I1" => SlateStateV5::Invoice1,
|
|
||||||
"I2" => SlateStateV5::Invoice2,
|
|
||||||
"I3" => SlateStateV5::Invoice3,
|
|
||||||
_ => return Err(Error::custom("Invalid Slate state")),
|
|
||||||
};
|
|
||||||
Ok(retval)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serializes an secp256k1 pubkey to base64
|
/// Serializes an secp256k1 pubkey to base64
|
||||||
pub mod uuid_base64 {
|
pub mod uuid_base64 {
|
||||||
|
|||||||
@@ -54,18 +54,19 @@
|
|||||||
//! * `rsig` may be omitted if it has not yet been filled out
|
//! * `rsig` may be omitted if it has not yet been filled out
|
||||||
|
|
||||||
use crate::grin_core::core::FeeFields;
|
use crate::grin_core::core::FeeFields;
|
||||||
use crate::grin_core::core::{Input, Output, TxKernel};
|
|
||||||
use crate::grin_core::libtx::secp_ser;
|
use crate::grin_core::libtx::secp_ser;
|
||||||
use crate::grin_keychain::{BlindingFactor, Identifier};
|
use crate::grin_keychain::BlindingFactor;
|
||||||
use crate::grin_util::secp;
|
use crate::slate_versions::ser;
|
||||||
use crate::grin_util::secp::key::PublicKey;
|
|
||||||
use crate::grin_util::secp::pedersen::{Commitment, RangeProof};
|
|
||||||
use crate::grin_util::secp::Signature;
|
|
||||||
use crate::{slate_versions::ser, CbData};
|
|
||||||
use ed25519_dalek::Signature as DalekSignature;
|
use ed25519_dalek::Signature as DalekSignature;
|
||||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub use crate::slate_versions::common::{
|
||||||
|
sig_is_blank, Coinbase as CoinbaseV4, Commits as CommitsV4,
|
||||||
|
KernelFeaturesArgs as KernelFeaturesArgsV4, OutputFeatures as OutputFeaturesV4,
|
||||||
|
ParticipantData as ParticipantDataV4, SlateState as SlateStateV4,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct SlateV4 {
|
pub struct SlateV4 {
|
||||||
// Required Fields
|
// Required Fields
|
||||||
@@ -163,32 +164,6 @@ fn default_kernel_features_none() -> Option<KernelFeaturesArgsV4> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Slate state definition
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub enum SlateStateV4 {
|
|
||||||
/// Unknown, coming from earlier versions of the slate
|
|
||||||
Unknown,
|
|
||||||
/// Standard flow, freshly init
|
|
||||||
Standard1,
|
|
||||||
/// Standard flow, return journey
|
|
||||||
Standard2,
|
|
||||||
/// Standard flow, ready for transaction posting
|
|
||||||
Standard3,
|
|
||||||
/// Invoice flow, freshly init
|
|
||||||
Invoice1,
|
|
||||||
///Invoice flow, return journey
|
|
||||||
Invoice2,
|
|
||||||
/// Invoice flow, ready for tranasction posting
|
|
||||||
Invoice3,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
|
||||||
/// Kernel features arguments definition
|
|
||||||
pub struct KernelFeaturesArgsV4 {
|
|
||||||
/// Lock height, for HeightLocked
|
|
||||||
pub lock_hgt: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct VersionCompatInfoV4 {
|
pub struct VersionCompatInfoV4 {
|
||||||
/// The current version of the slate format
|
/// The current version of the slate format
|
||||||
@@ -197,25 +172,6 @@ pub struct VersionCompatInfoV4 {
|
|||||||
pub block_header_version: u16,
|
pub block_header_version: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct ParticipantDataV4 {
|
|
||||||
/// Public key corresponding to private blinding factor
|
|
||||||
#[serde(with = "secp_ser::pubkey_serde")]
|
|
||||||
pub xs: PublicKey,
|
|
||||||
/// Public key corresponding to private nonce
|
|
||||||
#[serde(with = "secp_ser::pubkey_serde")]
|
|
||||||
pub nonce: PublicKey,
|
|
||||||
/// Public partial signature
|
|
||||||
#[serde(default = "default_part_sig_none")]
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
#[serde(with = "secp_ser::option_sig_serde")]
|
|
||||||
pub part: Option<Signature>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_part_sig_none() -> Option<Signature> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct PaymentInfoV4 {
|
pub struct PaymentInfoV4 {
|
||||||
#[serde(with = "ser::dalek_pubkey_serde")]
|
#[serde(with = "ser::dalek_pubkey_serde")]
|
||||||
@@ -232,71 +188,6 @@ fn default_receiver_signature_none() -> Option<DalekSignature> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct CommitsV4 {
|
|
||||||
/// Options for an output's structure or use
|
|
||||||
#[serde(default = "default_output_feature")]
|
|
||||||
#[serde(skip_serializing_if = "output_feature_is_plain")]
|
|
||||||
pub f: OutputFeaturesV4,
|
|
||||||
/// The homomorphic commitment representing the output amount
|
|
||||||
#[serde(
|
|
||||||
serialize_with = "secp_ser::as_hex",
|
|
||||||
deserialize_with = "secp_ser::commitment_from_hex"
|
|
||||||
)]
|
|
||||||
pub c: Commitment,
|
|
||||||
/// A proof that the commitment is in the right range
|
|
||||||
/// Only applies for transaction outputs
|
|
||||||
#[serde(with = "ser::option_rangeproof_hex")]
|
|
||||||
#[serde(default = "default_range_proof")]
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub p: Option<RangeProof>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&Output> for CommitsV4 {
|
|
||||||
fn from(out: &Output) -> CommitsV4 {
|
|
||||||
CommitsV4 {
|
|
||||||
f: out.features().into(),
|
|
||||||
c: out.commitment(),
|
|
||||||
p: Some(out.proof()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will need to be reworked once we no longer support input features with "commit only" inputs.
|
|
||||||
impl From<&Input> for CommitsV4 {
|
|
||||||
fn from(input: &Input) -> CommitsV4 {
|
|
||||||
CommitsV4 {
|
|
||||||
f: input.features.into(),
|
|
||||||
c: input.commitment(),
|
|
||||||
p: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_output_feature() -> OutputFeaturesV4 {
|
|
||||||
OutputFeaturesV4(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_feature_is_plain(o: &OutputFeaturesV4) -> bool {
|
|
||||||
o.0 == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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() {
|
|
||||||
if *b != 0 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_range_proof() -> Option<RangeProof> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u64_is_blank(u: &u64) -> bool {
|
fn u64_is_blank(u: &u64) -> bool {
|
||||||
*u == 0
|
*u == 0
|
||||||
}
|
}
|
||||||
@@ -316,72 +207,3 @@ fn fee_is_zero(f: &FeeFields) -> bool {
|
|||||||
fn default_fee() -> FeeFields {
|
fn default_fee() -> FeeFields {
|
||||||
FeeFields::zero()
|
FeeFields::zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mining node requests new coinbase via the foreign api every time a new candidate block is built.
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct CoinbaseV4 {
|
|
||||||
/// Output
|
|
||||||
output: CbOutputV4,
|
|
||||||
/// Kernel
|
|
||||||
kernel: CbKernelV4,
|
|
||||||
/// Key Id
|
|
||||||
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.commitment(),
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -175,8 +175,8 @@ impl Readable for SlateOptFields {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SigsWrap(Vec<ParticipantDataV4>);
|
pub(super) struct SigsWrap(pub(super) Vec<ParticipantDataV4>);
|
||||||
struct SigsWrapRef<'a>(&'a Vec<ParticipantDataV4>);
|
pub(super) struct SigsWrapRef<'a>(pub(super) &'a Vec<ParticipantDataV4>);
|
||||||
|
|
||||||
impl<'a> Writeable for SigsWrapRef<'a> {
|
impl<'a> Writeable for SigsWrapRef<'a> {
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), grin_ser::Error> {
|
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), grin_ser::Error> {
|
||||||
@@ -278,8 +278,8 @@ impl Readable for SlateOptStructs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ComsWrap(Vec<CommitsV4>);
|
pub(super) struct ComsWrap(pub(super) Vec<CommitsV4>);
|
||||||
struct ComsWrapRef<'a>(&'a Vec<CommitsV4>);
|
pub(super) struct ComsWrapRef<'a>(pub(super) &'a Vec<CommitsV4>);
|
||||||
|
|
||||||
impl<'a> Writeable for ComsWrapRef<'a> {
|
impl<'a> Writeable for ComsWrapRef<'a> {
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), grin_ser::Error> {
|
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), grin_ser::Error> {
|
||||||
|
|||||||
@@ -28,21 +28,23 @@
|
|||||||
//! * `memo` adds optional payment details
|
//! * `memo` adds optional payment details
|
||||||
|
|
||||||
use crate::grin_core::core::FeeFields;
|
use crate::grin_core::core::FeeFields;
|
||||||
use crate::grin_core::core::{Input, Output, TxKernel};
|
|
||||||
use crate::grin_core::libtx::secp_ser;
|
use crate::grin_core::libtx::secp_ser;
|
||||||
use crate::grin_keychain::{BlindingFactor, Identifier};
|
use crate::grin_keychain::BlindingFactor;
|
||||||
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::{PaymentMemo, PaymentProofType};
|
use crate::slate::{PaymentMemo, PaymentProofType};
|
||||||
use crate::{slate_versions::ser, CbData};
|
use crate::slate_versions::ser;
|
||||||
use chrono::prelude::{DateTime, Utc};
|
use chrono::prelude::{DateTime, Utc};
|
||||||
use ed25519_dalek::Signature as DalekSignature;
|
use ed25519_dalek::Signature as DalekSignature;
|
||||||
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
||||||
use serde_with::TimestampSeconds;
|
use serde_with::TimestampSeconds;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
// These fields have the same representation in V4 and V5
|
||||||
|
pub use crate::slate_versions::common::{
|
||||||
|
sig_is_blank, Coinbase as CoinbaseV5, Commits as CommitsV5,
|
||||||
|
KernelFeaturesArgs as KernelFeaturesArgsV5, OutputFeatures as OutputFeaturesV5,
|
||||||
|
ParticipantData as ParticipantDataV5, SlateState as SlateStateV5,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct SlateV5 {
|
pub struct SlateV5 {
|
||||||
// Required Fields
|
// Required Fields
|
||||||
@@ -140,32 +142,6 @@ fn default_kernel_features_none() -> Option<KernelFeaturesArgsV5> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Slate state definition
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub enum SlateStateV5 {
|
|
||||||
/// Unknown, coming from earlier versions of the slate
|
|
||||||
Unknown,
|
|
||||||
/// Standard flow, freshly init
|
|
||||||
Standard1,
|
|
||||||
/// Standard flow, return journey
|
|
||||||
Standard2,
|
|
||||||
/// Standard flow, ready for transaction posting
|
|
||||||
Standard3,
|
|
||||||
/// Invoice flow, freshly init
|
|
||||||
Invoice1,
|
|
||||||
///Invoice flow, return journey
|
|
||||||
Invoice2,
|
|
||||||
/// Invoice flow, ready for tranasction posting
|
|
||||||
Invoice3,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
|
||||||
/// Kernel features arguments definition
|
|
||||||
pub struct KernelFeaturesArgsV5 {
|
|
||||||
/// Lock height, for HeightLocked
|
|
||||||
pub lock_hgt: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct VersionCompatInfoV5 {
|
pub struct VersionCompatInfoV5 {
|
||||||
/// The current version of the slate format
|
/// The current version of the slate format
|
||||||
@@ -174,25 +150,6 @@ pub struct VersionCompatInfoV5 {
|
|||||||
pub block_header_version: u16,
|
pub block_header_version: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct ParticipantDataV5 {
|
|
||||||
/// Public key corresponding to private blinding factor
|
|
||||||
#[serde(with = "secp_ser::pubkey_serde")]
|
|
||||||
pub xs: PublicKey,
|
|
||||||
/// Public key corresponding to private nonce
|
|
||||||
#[serde(with = "secp_ser::pubkey_serde")]
|
|
||||||
pub nonce: PublicKey,
|
|
||||||
/// Public partial signature
|
|
||||||
#[serde(default = "default_part_sig_none")]
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
#[serde(with = "secp_ser::option_sig_serde")]
|
|
||||||
pub part: Option<Signature>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_part_sig_none() -> Option<Signature> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct PaymentInfoV5 {
|
pub struct PaymentInfoV5 {
|
||||||
@@ -218,71 +175,6 @@ fn default_promise_signature_none() -> Option<DalekSignature> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct CommitsV5 {
|
|
||||||
/// Options for an output's structure or use
|
|
||||||
#[serde(default = "default_output_feature")]
|
|
||||||
#[serde(skip_serializing_if = "output_feature_is_plain")]
|
|
||||||
pub f: OutputFeaturesV5,
|
|
||||||
/// The homomorphic commitment representing the output amount
|
|
||||||
#[serde(
|
|
||||||
serialize_with = "secp_ser::as_hex",
|
|
||||||
deserialize_with = "secp_ser::commitment_from_hex"
|
|
||||||
)]
|
|
||||||
pub c: Commitment,
|
|
||||||
/// A proof that the commitment is in the right range
|
|
||||||
/// Only applies for transaction outputs
|
|
||||||
#[serde(with = "ser::option_rangeproof_hex")]
|
|
||||||
#[serde(default = "default_range_proof")]
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub p: Option<RangeProof>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&Output> for CommitsV5 {
|
|
||||||
fn from(out: &Output) -> CommitsV5 {
|
|
||||||
CommitsV5 {
|
|
||||||
f: out.features().into(),
|
|
||||||
c: out.commitment(),
|
|
||||||
p: Some(out.proof()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will need to be reworked once we no longer support input features with "commit only" inputs.
|
|
||||||
impl From<&Input> for CommitsV5 {
|
|
||||||
fn from(input: &Input) -> CommitsV5 {
|
|
||||||
CommitsV5 {
|
|
||||||
f: input.features.into(),
|
|
||||||
c: input.commitment(),
|
|
||||||
p: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_output_feature() -> OutputFeaturesV5 {
|
|
||||||
OutputFeaturesV5(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_feature_is_plain(o: &OutputFeaturesV5) -> bool {
|
|
||||||
o.0 == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Copy, Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct OutputFeaturesV5(pub u8);
|
|
||||||
|
|
||||||
pub fn sig_is_blank(s: &secp::Signature) -> bool {
|
|
||||||
for b in s.to_raw_data().iter() {
|
|
||||||
if *b != 0 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_range_proof() -> Option<RangeProof> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u64_is_blank(u: &u64) -> bool {
|
fn u64_is_blank(u: &u64) -> bool {
|
||||||
*u == 0
|
*u == 0
|
||||||
}
|
}
|
||||||
@@ -302,72 +194,3 @@ fn fee_is_zero(f: &FeeFields) -> bool {
|
|||||||
fn default_fee() -> FeeFields {
|
fn default_fee() -> FeeFields {
|
||||||
FeeFields::zero()
|
FeeFields::zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mining node requests new coinbase via the foreign api every time a new candidate block is built.
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct CoinbaseV5 {
|
|
||||||
/// Output
|
|
||||||
output: CbOutputV5,
|
|
||||||
/// Kernel
|
|
||||||
kernel: CbKernelV5,
|
|
||||||
/// Key Id
|
|
||||||
key_id: Option<Identifier>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CbData> for CoinbaseV5 {
|
|
||||||
fn from(cb: CbData) -> CoinbaseV5 {
|
|
||||||
CoinbaseV5 {
|
|
||||||
output: CbOutputV5::from(&cb.output),
|
|
||||||
kernel: CbKernelV5::from(&cb.kernel),
|
|
||||||
key_id: cb.key_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&Output> for CbOutputV5 {
|
|
||||||
fn from(output: &Output) -> CbOutputV5 {
|
|
||||||
CbOutputV5 {
|
|
||||||
features: CbOutputFeatures::Coinbase,
|
|
||||||
commit: output.commitment(),
|
|
||||||
proof: output.proof(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&TxKernel> for CbKernelV5 {
|
|
||||||
fn from(kernel: &TxKernel) -> CbKernelV5 {
|
|
||||||
CbKernelV5 {
|
|
||||||
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 CbOutputV5 {
|
|
||||||
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 CbKernelV5 {
|
|
||||||
features: CbKernelFeatures,
|
|
||||||
#[serde(serialize_with = "secp_ser::as_hex")]
|
|
||||||
excess: Commitment,
|
|
||||||
#[serde(with = "secp_ser::sig_serde")]
|
|
||||||
excess_sig: secp::Signature,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,13 +14,9 @@
|
|||||||
|
|
||||||
//! Wraps a V5 Slate into a V5 Binary slate
|
//! Wraps a V5 Slate into a V5 Binary slate
|
||||||
|
|
||||||
use crate::grin_core::core::transaction::OutputFeatures;
|
|
||||||
use crate::grin_core::ser as grin_ser;
|
use crate::grin_core::ser as grin_ser;
|
||||||
use crate::grin_core::ser::{Readable, Reader, Writeable, Writer};
|
use crate::grin_core::ser::{Readable, Reader, Writeable, Writer};
|
||||||
use crate::grin_keychain::BlindingFactor;
|
use crate::grin_keychain::BlindingFactor;
|
||||||
use crate::grin_util::secp::key::PublicKey;
|
|
||||||
use crate::grin_util::secp::pedersen::{Commitment, RangeProof};
|
|
||||||
use crate::grin_util::secp::Signature;
|
|
||||||
use crate::slate::{PaymentMemo, PaymentProofType};
|
use crate::slate::{PaymentMemo, PaymentProofType};
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use ed25519_dalek::Signature as DalekSignature;
|
use ed25519_dalek::Signature as DalekSignature;
|
||||||
@@ -28,90 +24,12 @@ use ed25519_dalek::VerifyingKey as DalekPublicKey;
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use crate::slate_versions::v5::{
|
use crate::slate_versions::v5::{
|
||||||
CommitsV5, KernelFeaturesArgsV5, ParticipantDataV5, PaymentInfoV5, SlateStateV5, SlateV5,
|
CommitsV5, KernelFeaturesArgsV5, PaymentInfoV5, SlateStateV5, SlateV5, VersionCompatInfoV5,
|
||||||
VersionCompatInfoV5,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::slate_versions::v4_bin::{SlateOptFields, UuidWrap};
|
use crate::slate_versions::v4_bin::{
|
||||||
|
ComsWrap, ComsWrapRef, SigsWrap, SigsWrapRef, SlateOptFields, UuidWrap,
|
||||||
impl Writeable for SlateStateV5 {
|
};
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), grin_ser::Error> {
|
|
||||||
let b = match self {
|
|
||||||
SlateStateV5::Unknown => 0,
|
|
||||||
SlateStateV5::Standard1 => 1,
|
|
||||||
SlateStateV5::Standard2 => 2,
|
|
||||||
SlateStateV5::Standard3 => 3,
|
|
||||||
SlateStateV5::Invoice1 => 4,
|
|
||||||
SlateStateV5::Invoice2 => 5,
|
|
||||||
SlateStateV5::Invoice3 => 6,
|
|
||||||
};
|
|
||||||
writer.write_u8(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Readable for SlateStateV5 {
|
|
||||||
fn read<R: Reader>(reader: &mut R) -> Result<SlateStateV5, grin_ser::Error> {
|
|
||||||
let b = reader.read_u8()?;
|
|
||||||
let sta = match b {
|
|
||||||
0 => SlateStateV5::Unknown,
|
|
||||||
1 => SlateStateV5::Standard1,
|
|
||||||
2 => SlateStateV5::Standard2,
|
|
||||||
3 => SlateStateV5::Standard3,
|
|
||||||
4 => SlateStateV5::Invoice1,
|
|
||||||
5 => SlateStateV5::Invoice2,
|
|
||||||
6 => SlateStateV5::Invoice3,
|
|
||||||
_ => SlateStateV5::Unknown,
|
|
||||||
};
|
|
||||||
Ok(sta)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SigsWrap(Vec<ParticipantDataV5>);
|
|
||||||
struct SigsWrapRef<'a>(&'a Vec<ParticipantDataV5>);
|
|
||||||
|
|
||||||
impl<'a> Writeable for SigsWrapRef<'a> {
|
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), grin_ser::Error> {
|
|
||||||
writer.write_u8(self.0.len() as u8)?;
|
|
||||||
for s in self.0.iter() {
|
|
||||||
//0 means part sig is not yet included
|
|
||||||
//1 means part sig included
|
|
||||||
if s.part.is_some() {
|
|
||||||
writer.write_u8(1)?;
|
|
||||||
} else {
|
|
||||||
writer.write_u8(0)?;
|
|
||||||
}
|
|
||||||
s.xs.write(writer)?;
|
|
||||||
s.nonce.write(writer)?;
|
|
||||||
if let Some(s) = s.part {
|
|
||||||
s.write(writer)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Readable for SigsWrap {
|
|
||||||
fn read<R: Reader>(reader: &mut R) -> Result<SigsWrap, grin_ser::Error> {
|
|
||||||
let sigs_len = reader.read_u8()?;
|
|
||||||
let sigs = {
|
|
||||||
let mut ret = vec![];
|
|
||||||
for _ in 0..sigs_len as usize {
|
|
||||||
let has_partial = reader.read_u8()?;
|
|
||||||
let c = ParticipantDataV5 {
|
|
||||||
xs: PublicKey::read(reader)?,
|
|
||||||
nonce: PublicKey::read(reader)?,
|
|
||||||
part: match has_partial {
|
|
||||||
1 => Some(Signature::read(reader)?),
|
|
||||||
0 | _ => None,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ret.push(c);
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
};
|
|
||||||
Ok(SigsWrap(sigs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialization of optional structs
|
/// Serialization of optional structs
|
||||||
struct SlateOptStructsRef<'a> {
|
struct SlateOptStructsRef<'a> {
|
||||||
@@ -169,53 +87,6 @@ impl Readable for SlateOptStructs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ComsWrap(Vec<CommitsV5>);
|
|
||||||
struct ComsWrapRef<'a>(&'a Vec<CommitsV5>);
|
|
||||||
|
|
||||||
impl<'a> Writeable for ComsWrapRef<'a> {
|
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), grin_ser::Error> {
|
|
||||||
writer.write_u16(self.0.len() as u16)?;
|
|
||||||
for o in self.0.iter() {
|
|
||||||
//0 means input
|
|
||||||
//1 means output with proof
|
|
||||||
if o.p.is_some() {
|
|
||||||
writer.write_u8(1)?;
|
|
||||||
} else {
|
|
||||||
writer.write_u8(0)?;
|
|
||||||
}
|
|
||||||
OutputFeatures::from(o.f).write(writer)?;
|
|
||||||
o.c.write(writer)?;
|
|
||||||
if let Some(p) = o.p {
|
|
||||||
p.write(writer)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Readable for ComsWrap {
|
|
||||||
fn read<R: Reader>(reader: &mut R) -> Result<ComsWrap, grin_ser::Error> {
|
|
||||||
let coms_len = reader.read_u16()?;
|
|
||||||
let coms = {
|
|
||||||
let mut ret = vec![];
|
|
||||||
for _ in 0..coms_len as usize {
|
|
||||||
let is_output = reader.read_u8()?;
|
|
||||||
let c = CommitsV5 {
|
|
||||||
f: OutputFeatures::read(reader)?.into(),
|
|
||||||
c: Commitment::read(reader)?,
|
|
||||||
p: match is_output {
|
|
||||||
1 => Some(RangeProof::read(reader)?),
|
|
||||||
0 | _ => None,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ret.push(c);
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
};
|
|
||||||
Ok(ComsWrap(coms))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ProofWrap(PaymentInfoV5);
|
struct ProofWrap(PaymentInfoV5);
|
||||||
struct ProofWrapRef<'a>(&'a PaymentInfoV5);
|
struct ProofWrapRef<'a>(&'a PaymentInfoV5);
|
||||||
|
|
||||||
@@ -485,8 +356,12 @@ impl Readable for SlateV5Bin {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn slate_v5_serialize_deserialize() {
|
fn slate_v5_serialize_deserialize() {
|
||||||
|
use crate::grin_core::core::transaction::OutputFeatures;
|
||||||
use crate::grin_util::from_hex;
|
use crate::grin_util::from_hex;
|
||||||
use crate::grin_util::secp::key::PublicKey;
|
use crate::grin_util::secp::key::PublicKey;
|
||||||
|
use crate::grin_util::secp::pedersen::{Commitment, RangeProof};
|
||||||
|
use crate::grin_util::secp::Signature;
|
||||||
|
use crate::slate_versions::v5::ParticipantDataV5;
|
||||||
use crate::Slate;
|
use crate::Slate;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use grin_core::global::{set_local_chain_type, ChainTypes};
|
use grin_core::global::{set_local_chain_type, ChainTypes};
|
||||||
|
|||||||
Reference in New Issue
Block a user