Skip to content

Commit 6df781e

Browse files
committed
Merge branch 'master' into ao-fix-backing-filtering-on-disputes
* master: Add READ_ONLY flag to contract call function (#4418) Format the README.md files (#4688) Typos in template README (#4687) [ci] Increase timeout for check-runtime-migration workflow (#4674)
2 parents cd583f7 + 3e84164 commit 6df781e

18 files changed

Lines changed: 851 additions & 484 deletions

File tree

.github/workflows/check-runtime-migration.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
# rococo and westend are disabled for now (no access to parity-chains.parity.io)
3535
check-runtime-migration:
3636
runs-on: arc-runners-polkadot-sdk-beefy
37-
timeout-minutes: 30
37+
timeout-minutes: 40
3838
needs: [set-image]
3939
container:
4040
image: ${{ needs.set-image.outputs.IMAGE }}

.github/workflows/checks-quick.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,22 @@ jobs:
117117
CONFIG: .github/.markdownlint.yaml
118118
run: |
119119
echo "Checking markdown formatting. More info: docs/contributor/markdown_linting.md"
120+
echo "To fix potential erros, you can run 'markdownlint --config .github/.markdownlint.yaml -f --ignore target .' locally."
120121
markdownlint --config "$CONFIG" --ignore target .
121122
check-umbrella:
122-
runs-on: arc-runners-polkadot-sdk
123+
runs-on: ubuntu-latest
123124
timeout-minutes: 10
124125
needs: [set-image]
125126
container:
126127
image: ${{ needs.set-image.outputs.IMAGE }}
127128
steps:
128129
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.0 (22. Sep 2023)
129130
- name: install python deps
130-
run: |
131-
sudo apt-get update && sudo apt-get install -y python3-pip python3
132-
pip3 install "cargo-workspace>=1.2.4" toml
131+
run: pip3 install "cargo-workspace>=1.2.4" toml
133132
- name: check umbrella correctness
134133
run: |
134+
# Fixes "detected dubious ownership" error in the ci
135+
git config --global --add safe.directory '*'
135136
python3 scripts/generate-umbrella.py --sdk . --version 0.1.0
136137
cargo +nightly fmt --all
137138

prdoc/pr_4418.prdoc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
2+
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
3+
4+
title: "[pallet_contracts] Add `READ_ONLY` flag to contract `call` function"
5+
6+
doc:
7+
- audience: Runtime User
8+
description: |
9+
This PR implements the `READ_ONLY` flag to be used as a `Callflag` in the contract `call` function.
10+
The flag indicates that the callee is restricted from modifying the state during call execution.
11+
It is equivalent to Ethereum's [STATICCALL](https://eips.ethereum.org/EIPS/eip-214).
12+
13+
crates:
14+
- name: pallet-contracts
15+
bump: minor
16+
- name: pallet-contracts-uapi
17+
bump: minor
18+
- name: pallet-contracts-proc-macro
19+
bump: minor
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
//! This fixture calls the account_id with the flags and value.
19+
#![no_std]
20+
#![no_main]
21+
22+
use common::input;
23+
use uapi::{HostFn, HostFnImpl as api};
24+
25+
#[no_mangle]
26+
#[polkavm_derive::polkavm_export]
27+
pub extern "C" fn deploy() {}
28+
29+
#[no_mangle]
30+
#[polkavm_derive::polkavm_export]
31+
pub extern "C" fn call() {
32+
input!(
33+
256,
34+
callee_addr: [u8; 32],
35+
flags: u32,
36+
value: u64,
37+
forwarded_input: [u8],
38+
);
39+
40+
api::call_v2(
41+
uapi::CallFlags::from_bits(flags).unwrap(),
42+
callee_addr,
43+
0u64, // How much ref_time to devote for the execution. 0 = all.
44+
0u64, // How much proof_size to devote for the execution. 0 = all.
45+
None, // No deposit limit.
46+
&value.to_le_bytes(), // Value transferred to the contract.
47+
forwarded_input,
48+
None,
49+
)
50+
.unwrap();
51+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
// This fixture tests if read-only call works as expected.
19+
#![no_std]
20+
#![no_main]
21+
22+
use common::input;
23+
use uapi::{HostFn, HostFnImpl as api};
24+
25+
#[no_mangle]
26+
#[polkavm_derive::polkavm_export]
27+
pub extern "C" fn deploy() {}
28+
29+
#[no_mangle]
30+
#[polkavm_derive::polkavm_export]
31+
pub extern "C" fn call() {
32+
input!(
33+
256,
34+
callee_addr: [u8; 32],
35+
callee_input: [u8],
36+
);
37+
38+
// Call the callee
39+
api::call_v2(
40+
uapi::CallFlags::READ_ONLY,
41+
callee_addr,
42+
0u64, // How much ref_time to devote for the execution. 0 = all.
43+
0u64, // How much proof_size to devote for the execution. 0 = all.
44+
None, // No deposit limit.
45+
&0u64.to_le_bytes(), // Value transferred to the contract.
46+
callee_input,
47+
None,
48+
)
49+
.unwrap();
50+
}

substrate/frame/contracts/proc-macro/src/lib.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,15 @@ impl HostFn {
170170

171171
// process attributes
172172
let msg =
173-
"Only #[version(<u8>)], #[unstable], #[prefixed_alias], #[cfg] and #[deprecated] attributes are allowed.";
173+
"Only #[version(<u8>)], #[unstable], #[prefixed_alias], #[cfg], #[mutating] and #[deprecated] attributes are allowed.";
174174
let span = item.span();
175175
let mut attrs = item.attrs.clone();
176176
attrs.retain(|a| !a.path().is_ident("doc"));
177177
let mut maybe_version = None;
178178
let mut is_stable = true;
179179
let mut alias_to = None;
180180
let mut not_deprecated = true;
181+
let mut mutating = false;
181182
let mut cfg = None;
182183
while let Some(attr) = attrs.pop() {
183184
let ident = attr.path().get_ident().ok_or(err(span, msg))?.to_string();
@@ -208,6 +209,12 @@ impl HostFn {
208209
}
209210
not_deprecated = false;
210211
},
212+
"mutating" => {
213+
if mutating {
214+
return Err(err(span, "#[mutating] can only be specified once"))
215+
}
216+
mutating = true;
217+
},
211218
"cfg" => {
212219
if cfg.is_some() {
213220
return Err(err(span, "#[cfg] can only be specified once"))
@@ -217,6 +224,16 @@ impl HostFn {
217224
id => return Err(err(span, &format!("Unsupported attribute \"{id}\". {msg}"))),
218225
}
219226
}
227+
228+
if mutating {
229+
let stmt = syn::parse_quote! {
230+
if ctx.ext().is_read_only() {
231+
return Err(Error::<E::T>::StateChangeDenied.into());
232+
}
233+
};
234+
item.block.stmts.insert(0, stmt);
235+
}
236+
220237
let name = item.sig.ident.to_string();
221238

222239
if !(is_stable || not_deprecated) {

substrate/frame/contracts/src/chain_extension.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ pub trait ChainExtension<C: Config> {
112112
/// In case of `Err` the contract execution is immediately suspended and the passed error
113113
/// is returned to the caller. Otherwise the value of [`RetVal`] determines the exit
114114
/// behaviour.
115+
///
116+
/// # Note
117+
///
118+
/// The [`Self::call`] can be invoked within a read-only context, where any state-changing calls
119+
/// are disallowed. This information can be obtained using `env.ext().is_read_only()`. It is
120+
/// crucial for the implementer to handle this scenario appropriately.
115121
fn call<E: Ext<T = C>>(&mut self, env: Environment<E, InitState>) -> Result<RetVal>;
116122

117123
/// Determines whether chain extensions are enabled for this chain.

0 commit comments

Comments
 (0)