Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

pallet-contracts: Fix 16bit func_id #11985

Merged
merged 1 commit into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions frame/contracts/src/chain_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
//!
//! However, only extensions implementing [`RegisteredChainExtension`] can be put into a tuple.
//! This is because the [`RegisteredChainExtension::ID`] is used to decide which of those extensions
//! should should be used when the contract calls a chain extensions. Extensions which are generally
//! should be used when the contract calls a chain extensions. Extensions which are generally
//! useful should claim their `ID` with [the registry](https://github.com/paritytech/chainextension-registry)
//! so that no collisions with other vendors will occur.
//!
Expand Down Expand Up @@ -215,7 +215,7 @@ where
/// It returns the two least significant bytes of the `id` passed by a contract as the other
/// two bytes represent the chain extension itself (the code which is calling this function).
pub fn func_id(&self) -> u16 {
(self.inner.id & 0x00FF) as u16
(self.inner.id & 0x0000FFFF) as u16
}

/// The chain extension id within the `id` passed by a contract.
Expand Down
29 changes: 15 additions & 14 deletions frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,28 +158,28 @@ impl ChainExtension<Test> for TestExtension {
let func_id = env.func_id();
let id = env.ext_id() as u32 | func_id as u32;
match func_id {
0 => {
0x8000 => {
let mut env = env.buf_in_buf_out();
let input = env.read(8)?;
env.write(&input, false, None)?;
TEST_EXTENSION.with(|e| e.borrow_mut().last_seen_buffer = input);
Ok(RetVal::Converging(id))
},
1 => {
0x8001 => {
let env = env.only_in();
TEST_EXTENSION.with(|e| {
e.borrow_mut().last_seen_inputs =
(env.val0(), env.val1(), env.val2(), env.val3())
});
Ok(RetVal::Converging(id))
},
2 => {
0x8002 => {
let mut env = env.buf_in_buf_out();
let weight = env.read(5)?[4].into();
env.charge_weight(weight)?;
Ok(RetVal::Converging(id))
},
3 => Ok(RetVal::Diverging { flags: ReturnFlags::REVERT, data: vec![42, 99] }),
0x8003 => Ok(RetVal::Diverging { flags: ReturnFlags::REVERT, data: vec![42, 99] }),
_ => {
panic!("Passed unknown id to test chain extension: {}", func_id);
},
Expand Down Expand Up @@ -1646,36 +1646,37 @@ fn chain_extension_works() {
),);
let addr = Contracts::contract_address(&ALICE, &hash, &[]);

// 0 = read input buffer and pass it through as output
let input: Vec<u8> = ExtensionInput { extension_id: 0, func_id: 0, extra: &[99] }.into();
// 0x8000 = read input buffer and pass it through as output
let input: Vec<u8> =
ExtensionInput { extension_id: 0, func_id: 0x8000, extra: &[99] }.into();
let result =
Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, input.clone(), false);
assert_eq!(TestExtension::last_seen_buffer(), input);
assert_eq!(result.result.unwrap().data, Bytes(input));

// 1 = treat inputs as integer primitives and store the supplied integers
// 0x8001 = treat inputs as integer primitives and store the supplied integers
Contracts::bare_call(
ALICE,
addr.clone(),
0,
GAS_LIMIT,
None,
ExtensionInput { extension_id: 0, func_id: 1, extra: &[] }.into(),
ExtensionInput { extension_id: 0, func_id: 0x8001, extra: &[] }.into(),
false,
)
.result
.unwrap();
// those values passed in the fixture
assert_eq!(TestExtension::last_seen_inputs(), (4, 4, 16, 12));

// 2 = charge some extra weight (amount supplied in the fifth byte)
// 0x8002 = charge some extra weight (amount supplied in the fifth byte)
let result = Contracts::bare_call(
ALICE,
addr.clone(),
0,
GAS_LIMIT,
None,
ExtensionInput { extension_id: 0, func_id: 2, extra: &[0] }.into(),
ExtensionInput { extension_id: 0, func_id: 0x8002, extra: &[0] }.into(),
false,
);
assert_ok!(result.result);
Expand All @@ -1686,7 +1687,7 @@ fn chain_extension_works() {
0,
GAS_LIMIT,
None,
ExtensionInput { extension_id: 0, func_id: 2, extra: &[42] }.into(),
ExtensionInput { extension_id: 0, func_id: 0x8002, extra: &[42] }.into(),
false,
);
assert_ok!(result.result);
Expand All @@ -1697,20 +1698,20 @@ fn chain_extension_works() {
0,
GAS_LIMIT,
None,
ExtensionInput { extension_id: 0, func_id: 2, extra: &[95] }.into(),
ExtensionInput { extension_id: 0, func_id: 0x8002, extra: &[95] }.into(),
false,
);
assert_ok!(result.result);
assert_eq!(result.gas_consumed, gas_consumed + 95);

// 3 = diverging chain extension call that sets flags to 0x1 and returns a fixed buffer
// 0x8003 = diverging chain extension call that sets flags to 0x1 and returns a fixed buffer
let result = Contracts::bare_call(
ALICE,
addr.clone(),
0,
GAS_LIMIT,
None,
ExtensionInput { extension_id: 0, func_id: 3, extra: &[] }.into(),
ExtensionInput { extension_id: 0, func_id: 0x8003, extra: &[] }.into(),
false,
)
.result
Expand Down