Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
24 changes: 24 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions prdoc/pr_9603.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
title: '[pallet-revive] Migrate unstable storage host functions to `Storage` pre-compile'
doc:
- audience: Runtime Dev
description: Migrates the unstable host functions `contains_storage`, `take_storage`,
and `clear_storage` to a new `Storage` pre-compile.
crates:
- name: pallet-revive
bump: patch
- name: pallet-revive-fixtures
bump: major
- name: pallet-revive-uapi
bump: major
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The prdoc CI check is complaining about the format of this file. I don't see any issue here though.

1 change: 1 addition & 0 deletions substrate/frame/revive/fixtures/build/_Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ edition = "2021"
uapi = { package = 'pallet-revive-uapi', features = ["unstable-hostfn"], default-features = false }
hex-literal = { version = "0.4.1", default-features = false }
polkavm-derive = { version = "0.27.0" }
const-crypto = { version = "0.3.0" }

[profile.release]
opt-level = 3
Expand Down
13 changes: 9 additions & 4 deletions substrate/frame/revive/fixtures/contracts/caller_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,22 @@ pub extern "C" fn call() {
assert!(matches!(res, Err(ReturnErrorCode::OutOfResources)));

// Fail to call the contract due to insufficient proof_size weight.
let mut output = [0u8; 4];
let res = api::call(
uapi::CallFlags::empty(),
&callee,
u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all.
load_code_proof_size, //just enough to load the contract
u64::MAX,
load_code_proof_size, // just enough to load the contract
&[u8::MAX; 32], // No deposit limit.
&value,
&INPUT,
None,
Some(&mut &mut output[..]),
);
assert!(matches!(res, Err(ReturnErrorCode::OutOfResources)));
assert!(matches!(res, Err(ReturnErrorCode::CalleeReverted)));

let mut decode_buf = [0u8; 4];
decode_buf[..4].copy_from_slice(&output[..4]);
assert_eq!(u32::from_le_bytes(decode_buf), ReturnErrorCode::OutOfResources as u32);

// Call the contract successfully.
let mut output = [0u8; 4];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@

//! This contract tests the storage APIs. It sets and clears storage values using the different
//! versions of the storage APIs.

#![no_std]
#![no_main]

include!("../panic_handler.rs");
include!("../sol_utils.rs");

use uapi::{HostFn, HostFnImpl as api, StorageFlags};

#[no_mangle]
Expand All @@ -36,9 +39,9 @@ fn test_storage_operations(flags: StorageFlags) {
small_value_padded[1] = 6;
small_value_padded[2] = 7;

api::clear_storage(flags, &KEY);
clear_storage::<api>(flags, &KEY);

assert_eq!(api::contains_storage(flags, &KEY), None);
assert_eq!(contains_storage::<api>(flags, &KEY), None);

let existing = api::set_storage_or_clear(flags, &KEY, &VALUE_A);
assert_eq!(existing, None);
Expand All @@ -54,7 +57,7 @@ fn test_storage_operations(flags: StorageFlags) {
api::get_storage_or_zero(flags, &KEY, &mut cleared);
assert_eq!(cleared, ZERO);

assert_eq!(api::contains_storage(flags, &KEY), None);
assert_eq!(contains_storage::<api>(flags, &KEY), None);

// Test retrieving a value smaller than 32 bytes
api::set_storage_or_clear(flags, &KEY, &small_value_padded);
Expand All @@ -69,7 +72,7 @@ fn test_storage_operations(flags: StorageFlags) {
}

// Clean up
api::clear_storage(flags, &KEY);
clear_storage::<api>(flags, &KEY);
}

#[no_mangle]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

#![no_std]
#![no_main]

include!("../panic_handler.rs");
include!("../sol_utils.rs");

use uapi::{input, HostFn, HostFnImpl as api, StorageFlags};

Expand All @@ -40,7 +42,7 @@ pub extern "C" fn call() {

// Burn some PoV, clear_storage consumes some PoV as in order to clear the storage we need to we
// need to read its size first.
api::clear_storage(StorageFlags::empty(), b"");
clear_storage::<api>(StorageFlags::empty(), b"");

let exit_status = uapi::ReturnFlags::from_bits(exit_status[0] as u32).unwrap();
api::return_value(exit_status, output);
Expand Down
20 changes: 12 additions & 8 deletions substrate/frame/revive/fixtures/contracts/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@

//! This contract tests the storage APIs. It sets and clears storage values using the different
//! versions of the storage APIs.

#![no_std]
#![no_main]

include!("../panic_handler.rs");
include!("../sol_utils.rs");

use uapi::{unwrap_output, HostFn, HostFnImpl as api, StorageFlags};

Expand All @@ -36,7 +39,7 @@ pub extern "C" fn call() {
const VALUE_3: [u8; 4] = [3u8; 4];

api::set_storage(StorageFlags::empty(), &KEY, &VALUE_1);
assert_eq!(api::contains_storage(StorageFlags::empty(), &KEY), Some(VALUE_1.len() as _));
assert_eq!(contains_storage::<api>(StorageFlags::empty(), &KEY), Some(VALUE_1.len() as _));
unwrap_output!(val, [0u8; 4], api::get_storage, StorageFlags::empty(), &KEY);
assert_eq!(**val, VALUE_1);

Expand All @@ -45,19 +48,20 @@ pub extern "C" fn call() {
unwrap_output!(val, [0u8; 4], api::get_storage, StorageFlags::empty(), &KEY);
assert_eq!(**val, VALUE_2);

api::clear_storage(StorageFlags::empty(), &KEY);
assert_eq!(api::contains_storage(StorageFlags::empty(), &KEY), None);
clear_storage::<api>(StorageFlags::empty(), &KEY);
assert_eq!(contains_storage::<api>(StorageFlags::empty(), &KEY), None);

let existing = api::set_storage(StorageFlags::empty(), &KEY, &VALUE_3);
assert_eq!(existing, None);
assert_eq!(api::contains_storage(StorageFlags::empty(), &KEY), Some(VALUE_1.len() as _));
assert_eq!(contains_storage::<api>(StorageFlags::empty(), &KEY), Some(VALUE_1.len() as _));
unwrap_output!(val, [0u8; 32], api::get_storage, StorageFlags::empty(), &KEY);
assert_eq!(**val, VALUE_3);

api::clear_storage(StorageFlags::empty(), &KEY);
assert_eq!(api::contains_storage(StorageFlags::empty(), &KEY), None);
clear_storage::<api>(StorageFlags::empty(), &KEY);
assert_eq!(contains_storage::<api>(StorageFlags::empty(), &KEY), None);
let existing = api::set_storage(StorageFlags::empty(), &KEY, &VALUE_3);
assert_eq!(existing, None);
unwrap_output!(val, [0u8; 32], api::take_storage, StorageFlags::empty(), &KEY);
assert_eq!(**val, VALUE_3);
let mut decoded_buf = [0u8; 4];
assert_eq!(take_storage::<api>(StorageFlags::empty(), &KEY, &mut decoded_buf), Some(4));
assert_eq!(decoded_buf, VALUE_3);
}
14 changes: 9 additions & 5 deletions substrate/frame/revive/fixtures/contracts/transient_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
// limitations under the License.

//! This contract tests the transient storage APIs.

#![no_std]
#![no_main]

include!("../panic_handler.rs");
include!("../sol_utils.rs");

use uapi::{unwrap_output, HostFn, HostFnImpl as api, StorageFlags};

Expand All @@ -36,7 +39,7 @@ pub extern "C" fn call() {

let existing = api::set_storage(StorageFlags::TRANSIENT, &KEY, &VALUE_1);
assert_eq!(existing, None);
assert_eq!(api::contains_storage(StorageFlags::TRANSIENT, &KEY), Some(VALUE_1.len() as _));
assert_eq!(contains_storage::<api>(StorageFlags::TRANSIENT, &KEY), Some(VALUE_1.len() as _));
unwrap_output!(val, [0u8; 32], api::get_storage, StorageFlags::TRANSIENT, &KEY);
assert_eq!(**val, VALUE_1);

Expand All @@ -45,11 +48,12 @@ pub extern "C" fn call() {
unwrap_output!(val, [0u8; 32], api::get_storage, StorageFlags::TRANSIENT, &KEY);
assert_eq!(**val, VALUE_2);

assert_eq!(api::clear_storage(StorageFlags::TRANSIENT, &KEY), Some(VALUE_2.len() as _));
assert_eq!(api::contains_storage(StorageFlags::TRANSIENT, &KEY), None);
assert_eq!(clear_storage::<api>(StorageFlags::TRANSIENT, &KEY), Some(VALUE_2.len() as _));
assert_eq!(contains_storage::<api>(StorageFlags::TRANSIENT, &KEY), None);

let existing = api::set_storage(StorageFlags::TRANSIENT, &KEY, &VALUE_3);
assert_eq!(existing, None);
unwrap_output!(val, [0u8; 128], api::take_storage, StorageFlags::TRANSIENT, &KEY);
assert_eq!(**val, VALUE_3);
let mut output = [0u8; 6];
let _ = take_storage::<api>(StorageFlags::TRANSIENT, &KEY, &mut output).expect("value must exist in storage");
assert_eq!(output, VALUE_3);
}
Loading
Loading