Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ab34400
Initial draft of tip enum
Jun 19, 2019
d36dc9a
Fix local tests
Jun 19, 2019
a18be8c
Builds.
kianenigma Jun 22, 2019
55d39cf
Fix test build.
kianenigma Jun 22, 2019
a4e2816
Tratify tip.
kianenigma Jun 23, 2019
58ae208
Cleanup of checkedExt.
kianenigma Jun 23, 2019
c7fe8bf
More cleanup.
kianenigma Jun 23, 2019
e47bf96
Master.into()
kianenigma Jun 23, 2019
78dde21
Checked Tip + other fixes.
kianenigma Jun 27, 2019
7326e5a
Line width
kianenigma Jun 27, 2019
a568a9b
Update core/sr-primitives/src/generic/tip.rs
4meta5 Jun 28, 2019
b3f69cb
Fix build.
kianenigma Jun 28, 2019
557f6c5
Merge branch 'master' of github.com:paritytech/substrate into kiz-tx-tip
kianenigma Jun 28, 2019
8e713aa
Bump.
kianenigma Jun 28, 2019
b110af6
Merge branch 'kiz-tx-tip' of github.com:paritytech/substrate into kiz…
kianenigma Jun 28, 2019
23df80d
Some cleanup (+should pass the tests).
kianenigma Jun 30, 2019
83721a4
Fix sync test payload.
kianenigma Jun 30, 2019
bd28f0d
Fix subkey and factory sig
kianenigma Jun 30, 2019
120de20
revert back old unchecked ext type to NOT use tip.
kianenigma Jul 9, 2019
0d1de9d
Make balance associated type of payment.
kianenigma Jul 10, 2019
6836f6b
Optionize tip.
kianenigma Jul 10, 2019
7191a7d
Further cleanup.
kianenigma Jul 10, 2019
0846065
Further cleanup.
kianenigma Jul 10, 2019
12ecfcc
Master.into()
kianenigma Jul 10, 2019
bf99e73
Fix tests.
kianenigma Jul 10, 2019
4824776
remove balance as generic.
kianenigma Jul 10, 2019
fb42e4e
Update doc.
kianenigma Jul 10, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/consensus/rhd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

//! DEPRECATED.
//!
//! BFT Agreement based on a rotating proposer in different rounds.
//!
//! Where this crate refers to input stream, should never logically conclude.
Expand Down
43 changes: 40 additions & 3 deletions core/sr-primitives/src/generic/checked_extrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,33 @@

use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay};
use crate::weights::{Weighable, Weight};
use crate::generic::tip::{Tip, Tippable};

/// Definition of something that the external world might want to say; its
/// existence implies that it has been checked and is good, particularly with
/// regards to the signature.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct CheckedExtrinsic<AccountId, Index, Call> {
pub struct CheckedExtrinsic<AccountId, Index, Call, Balance> {
/// Who this purports to be from and the number of extrinsics have come before
/// from the same signer, if anyone (note this is not a signature).
pub signed: Option<(AccountId, Index)>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub signed: Option<(AccountId, Index)>,
pub signed: Option<(AccountId, Index, Tip<Balance>)>,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it could theoretically be an option, but as long as it's compact encoded, then there's no point since zero compact encoded is a big as None encoded.

Copy link
Member

@gavofyork gavofyork Jul 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just make sure Tip<Balance> implements Default. For non-tipping chains, Tip<Balance> can be ().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it is part of the signature then it is only visible in signed txs which is the point of the current option. Hence, pub signed: Option<(AccountId, Index, Tip<Balance>)>, looks ok

/// The function that should be called.
pub function: Call,
/// An optional tip value that may or may not exist based on the underlying unchecked extrinsic.
///
/// Most often this is:
/// - `None` if the unchecked extrinsic does not have a tip OR it is unsigned.
/// - `Some` if the opposite.
pub tip: Option<Tip<Balance>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should just be an additional arg in signed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be moved there but you mean probably in unchecked_mortal_compact_tipped.rs (god, hate this name to type it)? I will also update here but this is not really important anymore.

}

impl<AccountId, Index, Call> traits::Applyable for CheckedExtrinsic<AccountId, Index, Call>
impl<AccountId, Index, Call, Balance> traits::Applyable for CheckedExtrinsic<AccountId, Index, Call, Balance>
where
AccountId: Member + MaybeDisplay,
Index: Member + MaybeDisplay + SimpleArithmetic,
Call: Member,
Balance: Member,
{
type Index = Index;
type AccountId = AccountId;
Expand All @@ -56,11 +64,40 @@ where
}
}

impl<AccountId, Index, Call> Weighable for CheckedExtrinsic<AccountId, Index, Call>
impl<AccountId, Index, Call, Balance> Weighable for CheckedExtrinsic<AccountId, Index, Call, Balance>
where
Call: Weighable,
{
fn weight(&self, len: usize) -> Weight {
self.function.weight(len)
}
}

/// `ExtBalance` is the balance type fed by the `check()` implementation of various unchecked
/// extrinsics. `NodeBalance` is the actual balance type used as a primitive type of the substrate
/// node.
///
/// In practice, if they underlying unchecked transaction is tip-aware, they are the same. Otherwise,
/// the tip is always `None` and the type is of no importance.
impl<AccountId, Index, Call, ExtBalance, NodeBalance> Tippable<NodeBalance>
for CheckedExtrinsic<AccountId, Index, Call, ExtBalance>
where
ExtBalance: Clone + Copy,
NodeBalance: From<ExtBalance>,
{
fn tip(&self) -> Option<Tip<NodeBalance>> {
// This is a hacky way to prevent `unchecked_mortal[_compact]_extrinsic` types, which
// don't have a tip, become generic over a balance type.
// Basically, this CheckedExtrinsic is built either 1- from an
// `UncheckedMortalCompactTippedExtrinsic`, which is tip-aware and hence, the second arm
// will be trivially executed and the type conversion will be safe (the compiler is probably
// smart enough to remove it in fact). In this case, NodeBalance and ExtBalance are the same.
// Or 2- this is built from all other types of uncheckedextrinsic which do not have tip and
// hence are not tip-aware. These modules will naively place a u32 (can be `()` in practice)
// as the type and it does not matter since `None` is used in this case (first arm).
match &self.tip {
None => None,
Some(Tip::Sender(v)) => Some(Tip::Sender(NodeBalance::from(*v))),
}
}
}
8 changes: 5 additions & 3 deletions core/sr-primitives/src/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,26 @@
mod unchecked_extrinsic;
mod unchecked_mortal_extrinsic;
mod unchecked_mortal_compact_extrinsic;
mod unchecked_mortal_compact_tipped_extrinsic;
mod era;
mod checked_extrinsic;
mod header;
mod block;
mod digest;
mod tip;
#[cfg(test)]
mod tests;

pub use self::unchecked_extrinsic::UncheckedExtrinsic;
pub use self::unchecked_mortal_extrinsic::UncheckedMortalExtrinsic;
pub use self::unchecked_mortal_compact_extrinsic::UncheckedMortalCompactExtrinsic;
pub use self::unchecked_mortal_compact_tipped_extrinsic::UncheckedMortalCompactTippedExtrinsic;
pub use self::era::{Era, Phase};
pub use self::checked_extrinsic::CheckedExtrinsic;
pub use self::header::Header;
pub use self::block::{Block, SignedBlock, BlockId};
pub use self::digest::{
Digest, DigestItem, DigestItemRef, OpaqueDigestItemId
};
pub use self::digest::{Digest, DigestItem, DigestItemRef, OpaqueDigestItemId};
pub use self::tip::{Tip, Tippable, NoTipBalance};

use crate::codec::Encode;
use rstd::prelude::*;
Expand Down
55 changes: 55 additions & 0 deletions core/sr-primitives/src/generic/tip.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.

// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

//! Tip structure for a transaction.
use crate::codec::{Encode, Decode};
use crate::traits::Zero;

/// A placeholder tip type that is used to fulfill the generic requirements of `checked_extrinsic`
/// when the underlying `unchecked_extrinsic` actually does not have a tip.
pub type NoTipBalance = u32;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not ()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could not have it meet the type requirements of the generic type (has to be SimpleArithmetic-- probably doable but needs a more handy rust dev with more time -- will try)


/// Representation of a transaction tip.
///
/// Provided as an enum to support potential future use cases such as:
/// - Tipped by a third party (software or exchange).
/// - Unsigned tip.
#[cfg_attr(feature = "std", derive(Debug))]
#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode)]
pub enum Tip<Balance> {
/// The sender of the transaction has included some tip.
///
/// this must be signed and included in the signature payload.
Sender(Balance),
}

impl<Balance: Zero + Copy> Tip<Balance> {
/// Return the raw value of the tip (to be burned or consumed) regardless of any logic that the
/// Tip enum variant might embody.
pub fn value(&self) -> Balance {
match *self {
Tip::Sender(value) => value,
}
}
}

/// A trait for a generic transaction that contains a tip. The tip itself might yield something
/// that translates to "no tip".
pub trait Tippable<Balance> {
/// Return the tip associated with this transaction.
fn tip(&self) -> Option<Tip<Balance>>;
}
5 changes: 4 additions & 1 deletion core/sr-primitives/src/generic/unchecked_extrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use std::fmt;
use rstd::prelude::*;
use crate::codec::{Decode, Encode, Codec, Input, HasCompact};
use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay, Lookup, Extrinsic};
use crate::generic::tip::NoTipBalance;
use super::CheckedExtrinsic;

#[derive(PartialEq, Eq, Clone, Encode, Decode)]
Expand Down Expand Up @@ -85,7 +86,7 @@ where
AccountId: Member + MaybeDisplay,
Context: Lookup<Source=Address, Target=AccountId>,
{
type Checked = CheckedExtrinsic<AccountId, Index, Call>;
type Checked = CheckedExtrinsic<AccountId, Index, Call, NoTipBalance>;

fn check(self, context: &Context) -> Result<Self::Checked, &'static str> {
Ok(match self.signature {
Expand All @@ -98,11 +99,13 @@ where
CheckedExtrinsic {
signed: Some((signed, payload.0)),
function: payload.1,
tip: None,
}
}
None => CheckedExtrinsic {
signed: None,
function: self.function,
tip: None,
},
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::codec::{Decode, Encode, Input, Compact};
use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash,
Lookup, Checkable, Extrinsic, SaturatedConversion};
use super::{CheckedExtrinsic, Era};
use crate::generic::tip::NoTipBalance;

const TRANSACTION_VERSION: u8 = 1;

Expand All @@ -40,7 +41,9 @@ pub struct UncheckedMortalCompactExtrinsic<Address, Index, Call, Signature> {
pub function: Call,
}

impl<Address, Index, Call, Signature> UncheckedMortalCompactExtrinsic<Address, Index, Call, Signature> {
impl<Address, Index, Call, Signature>
UncheckedMortalCompactExtrinsic<Address, Index, Call, Signature>
{
/// New instance of a signed extrinsic aka "transaction".
pub fn new_signed(index: Index, function: Call, signed: Address, signature: Signature, era: Era) -> Self {
UncheckedMortalCompactExtrinsic {
Expand All @@ -58,7 +61,9 @@ impl<Address, Index, Call, Signature> UncheckedMortalCompactExtrinsic<Address, I
}
}

impl<Address: Encode, Index: Encode, Call: Encode, Signature: Encode> Extrinsic for UncheckedMortalCompactExtrinsic<Address, Index, Call, Signature> {
impl<Address: Encode, Index: Encode, Call: Encode, Signature: Encode> Extrinsic
for UncheckedMortalCompactExtrinsic<Address, Index, Call, Signature>
{
fn is_signed(&self) -> Option<bool> {
Some(self.signature.is_some())
}
Expand All @@ -79,7 +84,9 @@ where
+ CurrentHeight<BlockNumber=BlockNumber>
+ BlockNumberToHash<BlockNumber=BlockNumber, Hash=Hash>,
{
type Checked = CheckedExtrinsic<AccountId, Index, Call>;
/// NOTE: this transaction is not tipped i.e. the tip value will be `None`. It does not really
/// matter what the last generic is since it is always `None`.
type Checked = CheckedExtrinsic<AccountId, Index, Call, NoTipBalance>;

fn check(self, context: &Context) -> Result<Self::Checked, &'static str> {
Ok(match self.signature {
Expand All @@ -101,11 +108,13 @@ where
CheckedExtrinsic {
signed: Some((signed, (raw_payload.0).0)),
function: raw_payload.1,
tip: None,
}
}
None => CheckedExtrinsic {
signed: None,
function: self.function,
tip: None,
},
})
}
Expand Down Expand Up @@ -177,13 +186,19 @@ impl<Address: Encode, Index, Signature: Encode, Call: Encode> serde::Serialize
}

#[cfg(feature = "std")]
impl<Address, Index, Call, Signature> fmt::Debug for UncheckedMortalCompactExtrinsic<Address, Index, Call, Signature> where
impl<Address, Index, Call, Signature> fmt::Debug for UncheckedMortalCompactExtrinsic<Address, Index, Call, Signature>
where
Address: fmt::Debug,
Index: fmt::Debug,
Call: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "UncheckedMortalCompactExtrinsic({:?}, {:?})", self.signature.as_ref().map(|x| (&x.0, &x.2)), self.function)
write!(
f,
"UncheckedMortalCompactExtrinsic({:?}, {:?})",
self.signature.as_ref().map(|x| (&x.0, &x.2)),
self.function
)
}
}

Expand Down Expand Up @@ -222,7 +237,7 @@ mod tests {
const DUMMY_ACCOUNTID: u64 = 0;

type Ex = UncheckedMortalCompactExtrinsic<u64, u64, Vec<u8>, TestSig>;
type CEx = CheckedExtrinsic<u64, u64, Vec<u8>>;
type CEx = CheckedExtrinsic<u64, u64, Vec<u8>, NoTipBalance>;

#[test]
fn unsigned_codec_should_work() {
Expand Down Expand Up @@ -263,21 +278,30 @@ mod tests {
fn immortal_signed_check_should_work() {
let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), vec![0u8;0], Era::immortal(), 0u64).encode()), Era::immortal());
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(<Ex as Checkable<TestContext>>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] }));
assert_eq!(
<Ex as Checkable<TestContext>>::check(ux, &TestContext),
Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0], tip: None })
);
}

#[test]
fn mortal_signed_check_should_work() {
let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), vec![0u8;0], Era::mortal(32, 42), 42u64).encode()), Era::mortal(32, 42));
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(<Ex as Checkable<TestContext>>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] }));
assert_eq!(
<Ex as Checkable<TestContext>>::check(ux, &TestContext),
Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0], tip: None })
);
}

#[test]
fn later_mortal_signed_check_should_work() {
let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), vec![0u8;0], Era::mortal(32, 11), 11u64).encode()), Era::mortal(32, 11));
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(<Ex as Checkable<TestContext>>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] }));
assert_eq!(
<Ex as Checkable<TestContext>>::check(ux, &TestContext),
Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0], tip: None })
);
}

#[test]
Expand Down
Loading