Pass topics along with events (#2563)

* Introduce an IndexedEvent

* Plumb topics through the Ext interface.

* Add topics to ext_deposit_event

* Charging for events.

* Check the number of topics.

* Check for duplicate topics.

* Bump API version.

* Move derive(*Eq) under test.

* Use sorting for finding duplicates.
This commit is contained in:
Sergei Pepyakin
2019-05-14 12:09:51 +02:00
committed by Gavin Wood
parent 6ccdbea01c
commit d57f6f9305
6 changed files with 272 additions and 52 deletions
+55 -15
View File
@@ -29,6 +29,9 @@ pub type CallOf<T> = <T as Trait>::Call;
pub type MomentOf<T> = <T as timestamp::Trait>::Moment;
pub type SeedOf<T> = <T as system::Trait>::Hash;
/// A type that represents a topic of an event. At the moment a hash is used.
pub type TopicOf<T> = <T as system::Trait>::Hash;
#[cfg_attr(test, derive(Debug))]
pub struct InstantiateReceipt<AccountId> {
pub address: AccountId,
@@ -106,8 +109,10 @@ pub trait Ext {
/// Returns a reference to the random seed for the current block
fn random_seed(&self) -> &SeedOf<Self::T>;
/// Deposit an event.
fn deposit_event(&mut self, data: Vec<u8>);
/// Deposit an event with the given topics.
///
/// There should not be any duplicates in `topics`.
fn deposit_event(&mut self, topics: Vec<TopicOf<Self::T>>, data: Vec<u8>);
/// Set rent allowance of the contract
fn set_rent_allowance(&mut self, rent_allowance: BalanceOf<Self::T>);
@@ -189,6 +194,15 @@ impl VmExecResult {
}
}
/// Struct that records a request to deposit an event with a list of topics.
#[cfg_attr(any(feature = "std", test), derive(Debug, PartialEq, Eq))]
pub struct IndexedEvent<T: Trait> {
/// A list of topics this event will be deposited with.
pub topics: Vec<T::Hash>,
/// The event to deposit.
pub event: Event<T>,
}
/// A trait that represent a virtual machine.
///
/// You can view a virtual machine as something that takes code, an input data buffer,
@@ -238,7 +252,7 @@ pub struct ExecutionContext<'a, T: Trait + 'a, V, L> {
pub self_trie_id: Option<TrieId>,
pub overlay: OverlayAccountDb<'a, T>,
pub depth: usize,
pub events: Vec<Event<T>>,
pub events: Vec<IndexedEvent<T>>,
pub calls: Vec<(T::AccountId, T::Call)>,
pub config: &'a Config<T>,
pub vm: &'a V,
@@ -418,7 +432,10 @@ where
.into_result()?;
// Deposit an instantiation event.
nested.events.push(RawEvent::Instantiated(self.self_account.clone(), dest.clone()));
nested.events.push(IndexedEvent {
event: RawEvent::Instantiated(self.self_account.clone(), dest.clone()),
topics: Vec::new(),
});
(nested.overlay.into_change_set(), nested.events, nested.calls)
};
@@ -545,8 +562,10 @@ fn transfer<'a, T: Trait, V: Vm<T>, L: Loader<T>>(
if transactor != dest {
ctx.overlay.set_balance(transactor, new_from_balance);
ctx.overlay.set_balance(dest, new_to_balance);
ctx.events
.push(RawEvent::Transfer(transactor.clone(), dest.clone(), value));
ctx.events.push(IndexedEvent {
event: RawEvent::Transfer(transactor.clone(), dest.clone(), value),
topics: Vec::new(),
});
}
Ok(())
@@ -631,8 +650,11 @@ where
&self.timestamp
}
fn deposit_event(&mut self, data: Vec<u8>) {
self.ctx.events.push(RawEvent::Contract(self.ctx.self_account.clone(), data));
fn deposit_event(&mut self, topics: Vec<T::Hash>, data: Vec<u8>) {
self.ctx.events.push(IndexedEvent {
topics,
event: RawEvent::Contract(self.ctx.self_account.clone(), data),
});
}
fn set_rent_allowance(&mut self, rent_allowance: BalanceOf<T>) {
@@ -659,7 +681,7 @@ where
mod tests {
use super::{
BalanceOf, ExecFeeToken, ExecutionContext, Ext, Loader, EmptyOutputBuf, TransferFeeKind, TransferFeeToken,
Vm, VmExecResult, InstantiateReceipt, RawEvent,
Vm, VmExecResult, InstantiateReceipt, RawEvent, IndexedEvent,
};
use crate::account_db::AccountDb;
use crate::gas::GasMeter;
@@ -1262,8 +1284,14 @@ mod tests {
// there are instantiation event.
assert_eq!(ctx.overlay.get_code_hash(&created_contract_address).unwrap(), dummy_ch);
assert_eq!(&ctx.events, &[
RawEvent::Transfer(ALICE, created_contract_address, 100),
RawEvent::Instantiated(ALICE, created_contract_address),
IndexedEvent {
event: RawEvent::Transfer(ALICE, created_contract_address, 100),
topics: Vec::new(),
},
IndexedEvent {
event: RawEvent::Instantiated(ALICE, created_contract_address),
topics: Vec::new(),
}
]);
}
);
@@ -1314,9 +1342,18 @@ mod tests {
// there are instantiation event.
assert_eq!(ctx.overlay.get_code_hash(&created_contract_address).unwrap(), dummy_ch);
assert_eq!(&ctx.events, &[
RawEvent::Transfer(ALICE, BOB, 20),
RawEvent::Transfer(BOB, created_contract_address, 15),
RawEvent::Instantiated(BOB, created_contract_address),
IndexedEvent {
event: RawEvent::Transfer(ALICE, BOB, 20),
topics: Vec::new(),
},
IndexedEvent {
event: RawEvent::Transfer(BOB, created_contract_address, 15),
topics: Vec::new(),
},
IndexedEvent {
event: RawEvent::Instantiated(BOB, created_contract_address),
topics: Vec::new(),
},
]);
}
);
@@ -1362,7 +1399,10 @@ mod tests {
// The contract wasn't created so we don't expect to see an instantiation
// event here.
assert_eq!(&ctx.events, &[
RawEvent::Transfer(ALICE, BOB, 20),
IndexedEvent {
event: RawEvent::Transfer(ALICE, BOB, 20),
topics: Vec::new(),
},
]);
}
);