Skip to content

Commit

Permalink
[pallet-revive] update generic runtime types (#5608)
Browse files Browse the repository at this point in the history
fix #5574

- Use U256 instead of BalanceOf<T> and MomentOf<T> in Ext trait
- Enforce H256 for T::Hash

The Ext trait still depends on the associated type `T: Config`, we can
look into refactoring it even more later but even in the current state
it should not influence how the data is encoded / decoded between the
contract and the host
```
fn caller(&self) -> Origin<Self::T>;
-> only use to extract the address of the caller 

fn account_id(&self) -> &AccountIdOf<Self::T>;
 -> only used to expose the address or access the account_id internally   

fn gas_meter(&self) -> &GasMeter<Self::T>;
fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T>;
 -> encoding does not depend on T

fn call_runtime(&self, call: <Self::T as Config>::RuntimeCall) -> DispatchResultWithPostInfo;
-> Substrate specific, just an opaque blob of bytes from the contract's perspective

fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
-> gated by #[cfg(any(test, feature = "runtime-benchmarks"))]
```
  • Loading branch information
pgherveou authored Sep 8, 2024
1 parent 016421a commit a4da897
Show file tree
Hide file tree
Showing 35 changed files with 504 additions and 458 deletions.
16 changes: 16 additions & 0 deletions prdoc/pr_5608.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
title: "[pallet-revive] update runtime types"

doc:
- audience: Runtime Dev
description: |
Refactor the Ext trait to use U256 instead of BalanceOf<T> or MomentOf<T>

crates:
- name: pallet-revive
bump: major
- name: pallet-revive-uapi
bump: patch
- name: pallet-revive-fixtures
bump: patch


9 changes: 3 additions & 6 deletions substrate/frame/revive/fixtures/contracts/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#![no_std]
#![no_main]

use common::output;
use common::u64_output;
use uapi::{HostFn, HostFnImpl as api};

#[no_mangle]
Expand All @@ -28,9 +28,6 @@ pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
// Initialize buffer with 1s so that we can check that it is overwritten.
output!(balance, [1u8; 8], api::balance,);

// Assert that the balance is 0.
assert_eq!(&[0u8; 8], balance);
let balance = u64_output!(api::balance,);
assert_eq!(balance, 0);
}
8 changes: 4 additions & 4 deletions substrate/frame/revive/fixtures/contracts/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ pub extern "C" fn call() {
api::call(
uapi::CallFlags::empty(),
callee_addr,
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&0u64.to_le_bytes(), // Value transferred to the contract.
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
callee_input,
None,
)
Expand Down
10 changes: 5 additions & 5 deletions substrate/frame/revive/fixtures/contracts/call_return_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#![no_std]
#![no_main]

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

#[no_mangle]
Expand All @@ -41,10 +41,10 @@ pub extern "C" fn call() {
let err_code = match api::call(
uapi::CallFlags::empty(),
callee_addr,
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&100u64.to_le_bytes(), // Value transferred to the contract.
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&u256_bytes(100u64), // Value transferred to the contract.
input,
None,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ pub extern "C" fn call() {
api::call(
uapi::CallFlags::empty(),
callee_addr,
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&0u64.to_le_bytes(), // Value transferred to the contract.
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
callee_input,
None,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#![no_std]
#![no_main]

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

#[no_mangle]
Expand All @@ -40,10 +40,10 @@ pub extern "C" fn call() {
api::call(
uapi::CallFlags::from_bits(flags).unwrap(),
callee_addr,
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&value.to_le_bytes(), // Value transferred to the contract.
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&u256_bytes(value), // Value transferred to the contract.
forwarded_input,
None,
)
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/revive/fixtures/contracts/call_with_limit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ pub extern "C" fn call() {
callee_addr,
ref_time,
proof_size,
None, // No deposit limit.
&0u64.to_le_bytes(), // value transferred to the contract.
None, // No deposit limit.
&[0u8; 32], // value transferred to the contract.
forwarded_input,
None,
)
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/revive/fixtures/contracts/caller_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#![no_std]
#![no_main]

use common::input;
use common::{input, u256_bytes};
use uapi::{HostFn, HostFnImpl as api, ReturnErrorCode};

#[no_mangle]
Expand All @@ -32,7 +32,7 @@ pub extern "C" fn call() {

// The value to transfer on instantiation and calls. Chosen to be greater than existential
// deposit.
let value = 32768u64.to_le_bytes();
let value = u256_bytes(32768u64);
let salt = [0u8; 32];

// Callee will use the first 4 bytes of the input to return an exit status.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ pub extern "C" fn call() {
api::call(
uapi::CallFlags::ALLOW_REENTRY,
&addr,
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&0u64.to_le_bytes(), // Value transferred to the contract.
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
input,
None,
)
Expand Down
27 changes: 27 additions & 0 deletions substrate/frame/revive/fixtures/contracts/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,30 @@ macro_rules! unwrap_output {
$host_fn($($arg,)* $output).unwrap();
};
}

/// Call the host function and convert the [u8; 32] output to u64.
#[macro_export]
macro_rules! u64_output {
($host_fn:path, $($arg:expr),*) => {{
let mut buffer = [1u8; 32];
$host_fn($($arg,)* &mut buffer);
assert!(buffer[8..].iter().all(|&x| x == 0));
u64::from_le_bytes(buffer[..8].try_into().unwrap())
}};
}

/// Convert a u64 into a [u8; 32].
pub const fn u256_bytes(value: u64) -> [u8; 32] {
let mut buffer = [0u8; 32];
let bytes = value.to_le_bytes();

buffer[0] = bytes[0];
buffer[1] = bytes[1];
buffer[2] = bytes[2];
buffer[3] = bytes[3];
buffer[4] = bytes[4];
buffer[5] = bytes[5];
buffer[6] = bytes[6];
buffer[7] = bytes[7];
buffer
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub extern "C" fn call() {
buffer,
input: [u8; 4],
callee: &[u8; 20],
deposit_limit: [u8; 8],
deposit_limit: &[u8; 32],
);

// create 4 byte of storage before calling
Expand All @@ -46,7 +46,7 @@ pub extern "C" fn call() {
0u64, // How much ref_time weight to devote for the execution. 0 = all.
0u64, // How much proof_size weight to devote for the execution. 0 = all.
Some(deposit_limit),
&0u64.to_le_bytes(), // Value transferred to the contract.
&[0u8; 32], // Value transferred to the contract.
input,
None,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#![no_std]
#![no_main]

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

#[no_mangle]
Expand All @@ -32,10 +32,10 @@ pub extern "C" fn call() {
input!(
input: [u8; 4],
code_hash: &[u8; 32],
deposit_limit: [u8; 8],
deposit_limit: &[u8; 32],
);

let value = 10_000u64.to_le_bytes();
let value = u256_bytes(10_000u64);
let salt = [0u8; 32];
let mut address = [0u8; 20];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub extern "C" fn call() {
0u64, // How much ref_time weight to devote for the execution. 0 = all.
0u64, // How much proof_size weight to devote for the execution. 0 = all.
None,
&0u64.to_le_bytes(), // Value transferred to the contract.
&[0u8; 32], // Value transferred to the contract.
input,
None,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#![no_std]
#![no_main]

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

#[no_mangle]
Expand All @@ -39,9 +39,8 @@ pub extern "C" fn call() {

// Assert that `value_transferred` is equal to the value
// passed to the `caller` contract: 1337.
output!(value_transferred, [0u8; 8], api::value_transferred,);
let value_transferred = u64::from_le_bytes(value_transferred[..].try_into().unwrap());
assert_eq!(value_transferred, 1337);
let value = u64_output!(api::value_transferred,);
assert_eq!(value, 1337);

// Assert that ALICE is the caller of the contract.
let mut caller = [0u8; 20];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
#![no_std]
#![no_main]

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

const ADDRESS_KEY: [u8; 32] = [0u8; 32];
const VALUE: [u8; 8] = [0, 0, 1u8, 0, 0, 0, 0, 0];
const VALUE: [u8; 32] = u256_bytes(65536);

#[no_mangle]
#[polkavm_derive::polkavm_export]
Expand Down
11 changes: 4 additions & 7 deletions substrate/frame/revive/fixtures/contracts/drain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#![no_std]
#![no_main]

use common::output;
use common::{u256_bytes, u64_output};
use uapi::{HostFn, HostFnImpl as api};

#[no_mangle]
Expand All @@ -28,17 +28,14 @@ pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
output!(balance, [0u8; 8], api::balance,);
let balance = u64::from_le_bytes(balance[..].try_into().unwrap());

output!(minimum_balance, [0u8; 8], api::minimum_balance,);
let minimum_balance = u64::from_le_bytes(minimum_balance[..].try_into().unwrap());
let balance = u64_output!(api::balance,);
let minimum_balance = u64_output!(api::minimum_balance,);

// Make the transferred value exceed the balance by adding the minimum balance.
let balance = balance + minimum_balance;

// Try to self-destruct by sending more balance to the 0 address.
// The call will fail because a contract transfer has a keep alive requirement.
let res = api::transfer(&[0u8; 20], &balance.to_le_bytes());
let res = api::transfer(&[0u8; 20], &u256_bytes(balance));
assert!(matches!(res, Err(uapi::ReturnErrorCode::TransferFailed)));
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use uapi::{HostFn, HostFnImpl as api};
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {
let buffer = [1u8, 2, 3, 4];
api::deposit_event(&[0u8; 0], &buffer);
let topics = [[42u8; 32]; 1];
api::deposit_event(&topics, &buffer);
api::return_value(uapi::ReturnFlags::empty(), &buffer);
}

Expand Down
3 changes: 2 additions & 1 deletion substrate/frame/revive/fixtures/contracts/event_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub extern "C" fn call() {
input!(len: u32,);

let data = &BUFFER[..len as usize];
let topics = [[0u8; 32]; 0];

api::deposit_event(&[0u8; 0], data);
api::deposit_event(&topics, data);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#![no_std]
#![no_main]

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

#[no_mangle]
Expand All @@ -36,8 +36,8 @@ pub extern "C" fn call() {
0u64, // How much ref_time weight to devote for the execution. 0 = all.
0u64, /* How much proof_size weight to devote for the execution. 0 =
* all. */
None, // No deposit limit.
&10_000u64.to_le_bytes(), // Value to transfer.
None, // No deposit limit.
&u256_bytes(10_000u64), // Value to transfer.
input,
None,
None,
Expand Down
8 changes: 4 additions & 4 deletions substrate/frame/revive/fixtures/contracts/read_only_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ pub extern "C" fn call() {
api::call(
uapi::CallFlags::READ_ONLY,
callee_addr,
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&0u64.to_le_bytes(), // Value transferred to the contract.
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
callee_input,
None,
)
Expand Down
8 changes: 4 additions & 4 deletions substrate/frame/revive/fixtures/contracts/recurse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ pub extern "C" fn call() {
api::call(
uapi::CallFlags::ALLOW_REENTRY,
&addr,
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much deposit_limit to devote for the execution. 0 = all.
None, // No deposit limit.
&0u64.to_le_bytes(), // Value transferred to the contract.
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much deposit_limit to devote for the execution. 0 = all.
None, // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
&(calls_left - 1).to_le_bytes(),
None,
)
Expand Down
8 changes: 4 additions & 4 deletions substrate/frame/revive/fixtures/contracts/self_destruct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ pub extern "C" fn call() {
api::call(
uapi::CallFlags::ALLOW_REENTRY,
&addr,
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&0u64.to_le_bytes(), // Value to transfer.
0u64, // How much ref_time to devote for the execution. 0 = all.
0u64, // How much proof_size to devote for the execution. 0 = all.
None, // No deposit limit.
&[0u8; 32], // Value to transfer.
&[0u8; 0],
None,
)
Expand Down
Loading

0 comments on commit a4da897

Please sign in to comment.