Allow duplicate topics in smart contract events (#13065)

* Removed `has_duplicates` check form the `deposit_event`.
Removed the usage of `Error::DuplicateTopics`.

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts

Co-authored-by: command-bot <>
This commit is contained in:
Green Baneling
2023-01-11 13:22:22 +00:00
committed by GitHub
parent 406e8ca417
commit 643b69c64d
4 changed files with 986 additions and 992 deletions
-2
View File
@@ -816,8 +816,6 @@ pub mod pallet {
RandomSubjectTooLong,
/// The amount of topics passed to `seal_deposit_events` exceeds the limit.
TooManyTopics,
/// The topics passed to `seal_deposit_events` contains at least one duplicate.
DuplicateTopics,
/// The chain does not provide a chain extension. Calling the chain extension results
/// in this error. Note that this usually shouldn't happen as deploying such contracts
/// is rejected.
+46 -38
View File
@@ -1988,6 +1988,52 @@ mod tests {
assert!(mock_ext.gas_meter.gas_left().ref_time() > 0);
}
const CODE_DEPOSIT_EVENT_DUPLICATES: &str = r#"
(module
(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
(import "env" "memory" (memory 1 1))
(func (export "call")
(call $seal_deposit_event
(i32.const 32) ;; Pointer to the start of topics buffer
(i32.const 129) ;; The length of the topics buffer.
(i32.const 8) ;; Pointer to the start of the data buffer
(i32.const 13) ;; Length of the buffer
)
)
(func (export "deploy"))
(data (i32.const 8) "\00\01\2A\00\00\00\00\00\00\00\E5\14\00")
;; Encoded Vec<TopicOf<T>>, the buffer has length of 129 bytes.
(data (i32.const 32) "\10"
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04")
)
"#;
/// Checks that the runtime allows duplicate topics.
#[test]
fn deposit_event_duplicates_allowed() {
let mut mock_ext = MockExt::default();
assert_ok!(execute(CODE_DEPOSIT_EVENT_DUPLICATES, vec![], &mut mock_ext,));
assert_eq!(
mock_ext.events,
vec![(
vec![
H256::repeat_byte(0x01),
H256::repeat_byte(0x02),
H256::repeat_byte(0x01),
H256::repeat_byte(0x04)
],
vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]
)]
);
}
const CODE_DEPOSIT_EVENT_MAX_TOPICS: &str = r#"
(module
(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
@@ -2027,44 +2073,6 @@ mod tests {
);
}
const CODE_DEPOSIT_EVENT_DUPLICATES: &str = r#"
(module
(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
(import "env" "memory" (memory 1 1))
(func (export "call")
(call $seal_deposit_event
(i32.const 32) ;; Pointer to the start of topics buffer
(i32.const 129) ;; The length of the topics buffer.
(i32.const 8) ;; Pointer to the start of the data buffer
(i32.const 13) ;; Length of the buffer
)
)
(func (export "deploy"))
(data (i32.const 8) "\00\01\2A\00\00\00\00\00\00\00\E5\14\00")
;; Encoded Vec<TopicOf<T>>, the buffer has length of 129 bytes.
(data (i32.const 32) "\10"
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04")
)
"#;
/// Checks that the runtime traps if there are duplicates.
#[test]
fn deposit_event_duplicates() {
assert_eq!(
execute(CODE_DEPOSIT_EVENT_DUPLICATES, vec![], MockExt::default(),),
Err(ExecError {
error: Error::<Test>::DuplicateTopics.into(),
origin: ErrorOrigin::Caller,
})
);
}
/// calls `seal_block_number` compares the result with the constant 121.
const CODE_BLOCK_NUMBER: &str = r#"
(module
+1 -17
View File
@@ -2085,15 +2085,6 @@ pub mod env {
data_ptr: u32,
data_len: u32,
) -> Result<(), TrapReason> {
fn has_duplicates<T: Ord>(items: &mut Vec<T>) -> bool {
items.sort();
// Find any two consecutive equal elements.
items.windows(2).any(|w| match &w {
&[a, b] => a == b,
_ => false,
})
}
let num_topic = topics_len
.checked_div(sp_std::mem::size_of::<TopicOf<E::T>>() as u32)
.ok_or("Zero sized topics are not allowed")?;
@@ -2102,7 +2093,7 @@ pub mod env {
return Err(Error::<E::T>::ValueTooLarge.into())
}
let mut topics: Vec<TopicOf<<E as Ext>::T>> = match topics_len {
let topics: Vec<TopicOf<<E as Ext>::T>> = match topics_len {
0 => Vec::new(),
_ => ctx.read_sandbox_memory_as_unbounded(memory, topics_ptr, topics_len)?,
};
@@ -2112,13 +2103,6 @@ pub mod env {
return Err(Error::<E::T>::TooManyTopics.into())
}
// Check for duplicate topics. If there are any, then trap.
// Complexity O(n * log(n)) and no additional allocations.
// This also sorts the topics.
if has_duplicates(&mut topics) {
return Err(Error::<E::T>::DuplicateTopics.into())
}
let event_data = ctx.read_sandbox_memory(memory, data_ptr, data_len)?;
ctx.ext.deposit_event(topics, event_data);
File diff suppressed because it is too large Load Diff