-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Transaction timestamp condition #4419
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -104,6 +104,7 @@ use std::ops::Deref; | |
use std::cmp::Ordering; | ||
use std::cmp; | ||
use std::collections::{HashSet, HashMap, BTreeSet, BTreeMap}; | ||
use time; | ||
use linked_hash_map::LinkedHashMap; | ||
use util::{Address, H256, Uint, U256}; | ||
use util::table::Table; | ||
|
@@ -277,16 +278,16 @@ struct VerifiedTransaction { | |
/// Insertion time | ||
insertion_time: QueuingInstant, | ||
/// Delay until specifid block. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment not updated |
||
min_block: Option<BlockNumber>, | ||
condition: Option<Condition>, | ||
} | ||
|
||
impl VerifiedTransaction { | ||
fn new(transaction: SignedTransaction, origin: TransactionOrigin, time: QueuingInstant, min_block: Option<BlockNumber>) -> Self { | ||
fn new(transaction: SignedTransaction, origin: TransactionOrigin, time: QueuingInstant, condition: Option<Condition>) -> Self { | ||
VerifiedTransaction { | ||
transaction: transaction, | ||
origin: origin, | ||
insertion_time: time, | ||
min_block: min_block, | ||
condition: condition, | ||
} | ||
} | ||
|
||
|
@@ -666,14 +667,14 @@ impl TransactionQueue { | |
tx: SignedTransaction, | ||
origin: TransactionOrigin, | ||
time: QueuingInstant, | ||
min_block: Option<BlockNumber>, | ||
condition: Option<Condition>, | ||
details_provider: &TransactionDetailsProvider, | ||
) -> Result<TransactionImportResult, Error> { | ||
if origin == TransactionOrigin::Local { | ||
let hash = tx.hash(); | ||
let cloned_tx = tx.clone(); | ||
|
||
let result = self.add_internal(tx, origin, time, min_block, details_provider); | ||
let result = self.add_internal(tx, origin, time, condition, details_provider); | ||
match result { | ||
Ok(TransactionImportResult::Current) => { | ||
self.local_transactions.mark_pending(hash); | ||
|
@@ -694,7 +695,7 @@ impl TransactionQueue { | |
} | ||
result | ||
} else { | ||
self.add_internal(tx, origin, time, min_block, details_provider) | ||
self.add_internal(tx, origin, time, condition, details_provider) | ||
} | ||
} | ||
|
||
|
@@ -704,7 +705,7 @@ impl TransactionQueue { | |
tx: SignedTransaction, | ||
origin: TransactionOrigin, | ||
time: QueuingInstant, | ||
min_block: Option<BlockNumber>, | ||
condition: Option<Condition>, | ||
details_provider: &TransactionDetailsProvider, | ||
) -> Result<TransactionImportResult, Error> { | ||
if origin != TransactionOrigin::Local && tx.gas_price < self.minimal_gas_price { | ||
|
@@ -815,7 +816,7 @@ impl TransactionQueue { | |
} | ||
tx.check_low_s()?; | ||
// No invalid transactions beyond this point. | ||
let vtx = VerifiedTransaction::new(tx, origin, time, min_block); | ||
let vtx = VerifiedTransaction::new(tx, origin, time, condition); | ||
let r = self.import_tx(vtx, client_account.nonce).map_err(Error::Transaction); | ||
assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); | ||
r | ||
|
@@ -1082,7 +1083,12 @@ impl TransactionQueue { | |
if delayed.contains(&sender) { | ||
continue; | ||
} | ||
if tx.min_block.unwrap_or(0) > best_block { | ||
let delay = match tx.condition { | ||
Some(Condition::Number(n)) => n > best_block, | ||
Some(Condition::Timestamp(t)) => t > time::get_time().sec as u64, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be based off of the best block's timestamp rather than current time, since that's all that contracts can inspect. It's additionally often set into the future and not consistent with "real" time, but can be agreed upon unanimously just like block numbers There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Waiting for the block timestamp would result in transactions included no in the first available block, but in the next one. But at least the transaction is guaranteed not to fail, so I guess that's reasonable |
||
None => false, | ||
}; | ||
if delay { | ||
delayed.insert(sender); | ||
continue; | ||
} | ||
|
@@ -1100,7 +1106,7 @@ impl TransactionQueue { | |
/// Return all ready transactions. | ||
pub fn pending_transactions(&self, best_block: BlockNumber) -> Vec<PendingTransaction> { | ||
let mut r = Vec::new(); | ||
self.filter_pending_transaction(best_block, |tx| r.push(PendingTransaction::new(tx.transaction.clone(), tx.min_block))); | ||
self.filter_pending_transaction(best_block, |tx| r.push(PendingTransaction::new(tx.transaction.clone(), tx.condition.clone()))); | ||
r | ||
} | ||
|
||
|
@@ -1109,7 +1115,7 @@ impl TransactionQueue { | |
self.future.by_priority | ||
.iter() | ||
.map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`")) | ||
.map(|t| PendingTransaction { transaction: t.transaction.clone(), min_block: t.min_block }) | ||
.map(|t| PendingTransaction { transaction: t.transaction.clone(), condition: t.condition.clone() }) | ||
.collect() | ||
} | ||
|
||
|
@@ -1382,7 +1388,7 @@ pub mod test { | |
use super::{TransactionSet, TransactionOrder, VerifiedTransaction}; | ||
use miner::local_transactions::LocalTransactionsList; | ||
use client::TransactionImportResult; | ||
use transaction::{SignedTransaction, Transaction, Action}; | ||
use transaction::{SignedTransaction, Transaction, Action, Condition}; | ||
|
||
pub struct DummyTransactionDetailsProvider { | ||
account_details: AccountDetails, | ||
|
@@ -2178,7 +2184,7 @@ pub mod test { | |
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||
|
||
// when | ||
let res1 = txq.add(tx.clone(), TransactionOrigin::External, 0, Some(1), &default_tx_provider()).unwrap(); | ||
let res1 = txq.add(tx.clone(), TransactionOrigin::External, 0, Some(Condition::Number(1)), &default_tx_provider()).unwrap(); | ||
let res2 = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap(); | ||
|
||
// then | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,16 @@ impl Decodable for Action { | |
} | ||
} | ||
|
||
/// Transaction activation condition. | ||
#[derive(Debug, Clone, PartialEq, Eq)] | ||
#[cfg_attr(feature = "ipc", binary)] | ||
pub enum Condition { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: doc over attrs |
||
/// Valid at this block number or later. | ||
Number(BlockNumber), | ||
/// Valid at this unix time or later. | ||
Timestamp(u64), | ||
} | ||
|
||
/// A set of information describing an externally-originating message call | ||
/// or contract creation operation. | ||
#[derive(Default, Debug, Clone, PartialEq, Eq)] | ||
|
@@ -448,16 +458,16 @@ impl Deref for LocalizedTransaction { | |
pub struct PendingTransaction { | ||
/// Signed transaction data. | ||
pub transaction: SignedTransaction, | ||
/// To be activated at this block. `None` for immediately. | ||
pub min_block: Option<BlockNumber>, | ||
/// To be activated at this condition. `None` for immediately. | ||
pub condition: Option<Condition>, | ||
} | ||
|
||
impl PendingTransaction { | ||
/// Create a new pending transaction from signed transaction. | ||
pub fn new(signed: SignedTransaction, min_block: Option<BlockNumber>) -> Self { | ||
pub fn new(signed: SignedTransaction, condition: Option<Condition>) -> Self { | ||
PendingTransaction { | ||
transaction: signed, | ||
min_block: min_block, | ||
condition: condition, | ||
} | ||
} | ||
} | ||
|
@@ -466,7 +476,7 @@ impl From<SignedTransaction> for PendingTransaction { | |
fn from(t: SignedTransaction) -> Self { | ||
PendingTransaction { | ||
transaction: t, | ||
min_block: None, | ||
condition: None, | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this condition check needs updating as well. probably would be best done after changing
HeaderChain
to useethcore::encoded
(done locally).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given that it's "dead" code I don't mind merging this PR without it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll leave it to you then :)