Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
use BoundedVec for the debug buffer
  • Loading branch information
agryaznov committed Dec 6, 2022
commit b456323367238c31750f8ed6f89172d014a80a20
1 change: 1 addition & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,7 @@ impl pallet_contracts::Config for Runtime {
type MaxCodeLen = ConstU32<{ 128 * 1024 }>;
type MaxStorageKeyLen = ConstU32<128>;
type UnsafeUnstableInterface = ConstBool<false>;
type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>;
}

impl pallet_sudo::Config for Runtime {
Expand Down
31 changes: 13 additions & 18 deletions frame/contracts/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@
use crate::{
gas::GasMeter,
storage::{self, Storage, WriteOutcome},
BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, Determinism, Error, Event, Nonce,
Pallet as Contracts, Schedule,
BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, DebugBufferVec, Determinism, Error,
Event, Nonce, Pallet as Contracts, Schedule,
};
use frame_support::{
crypto::ecdsa::ECDSAExt,
dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable},
ensure,
storage::{with_transaction, TransactionOutcome},
traits::{Contains, Currency, ExistenceRequirement, OriginTrait, Randomness, Time},
weights::Weight,
Expand Down Expand Up @@ -410,7 +409,7 @@ pub struct Stack<'a, T: Config, E> {
///
/// All the bytes added to this field should be valid UTF-8. The buffer has no defined
/// structure and is intended to be shown to users as-is for debugging purposes.
debug_message: Option<&'a mut Vec<u8>>,
debug_message: Option<&'a mut DebugBufferVec<T>>,
/// The determinism requirement of this call stack.
determinism: Determinism,
/// No executable is held by the struct but influences its behaviour.
Expand Down Expand Up @@ -618,7 +617,7 @@ where
schedule: &'a Schedule<T>,
value: BalanceOf<T>,
input_data: Vec<u8>,
debug_message: Option<&'a mut Vec<u8>>,
debug_message: Option<&'a mut DebugBufferVec<T>>,
determinism: Determinism,
) -> Result<ExecReturnValue, ExecError> {
let (mut stack, executable) = Self::new(
Expand Down Expand Up @@ -653,7 +652,7 @@ where
value: BalanceOf<T>,
input_data: Vec<u8>,
salt: &[u8],
debug_message: Option<&'a mut Vec<u8>>,
debug_message: Option<&'a mut DebugBufferVec<T>>,
) -> Result<(T::AccountId, ExecReturnValue), ExecError> {
let (mut stack, executable) = Self::new(
FrameArgs::Instantiate {
Expand Down Expand Up @@ -682,7 +681,7 @@ where
storage_meter: &'a mut storage::meter::Meter<T>,
schedule: &'a Schedule<T>,
value: BalanceOf<T>,
debug_message: Option<&'a mut Vec<u8>>,
debug_message: Option<&'a mut DebugBufferVec<T>>,
determinism: Determinism,
) -> Result<(Self, E), ExecError> {
let (first_frame, executable, nonce) = Self::new_frame(
Expand Down Expand Up @@ -1332,12 +1331,7 @@ where
fn append_debug_buffer(&mut self, msg: &str) -> Result<bool, ()> {
if let Some(buffer) = &mut self.debug_message {
if !msg.is_empty() {
ensure!(
buffer.len().checked_add(msg.len()).ok_or(())? <=
self.schedule.limits.debug_buffer_len as usize,
()
);
buffer.extend(msg.as_bytes());
buffer.try_append(&mut msg.as_bytes().to_vec())?;
}
Ok(true)
} else {
Expand Down Expand Up @@ -2518,7 +2512,7 @@ mod tests {
exec_success()
});

let mut debug_buffer = Vec::new();
let mut debug_buffer = DebugBufferVec::<Test>::try_from(Vec::new()).unwrap();

ExtBuilder::default().build().execute_with(|| {
let min_balance = <Test as Config>::Currency::minimum_balance();
Expand All @@ -2541,7 +2535,7 @@ mod tests {
.unwrap();
});

assert_eq!(&String::from_utf8(debug_buffer).unwrap(), "This is a testMore text");
assert_eq!(&String::from_utf8(debug_buffer.to_vec()).unwrap(), "This is a testMore text");
}

#[test]
Expand All @@ -2556,7 +2550,7 @@ mod tests {
exec_trapped()
});

let mut debug_buffer = Vec::new();
let mut debug_buffer = DebugBufferVec::<Test>::try_from(Vec::new()).unwrap();

ExtBuilder::default().build().execute_with(|| {
let min_balance = <Test as Config>::Currency::minimum_balance();
Expand All @@ -2579,7 +2573,7 @@ mod tests {
assert!(result.is_err());
});

assert_eq!(&String::from_utf8(debug_buffer).unwrap(), "This is a testMore text");
assert_eq!(&String::from_utf8(debug_buffer.to_vec()).unwrap(), "This is a testMore text");
}

#[test]
Expand All @@ -2593,7 +2587,8 @@ mod tests {
});

// Pre-fill the buffer up to its limit
let mut debug_buffer = vec![0u8; schedule.limits.debug_buffer_len as usize];
let mut debug_buffer =
DebugBufferVec::<Test>::try_from(vec![0u8; DebugBufferVec::<Test>::bound()]).unwrap();

ExtBuilder::default().build().execute_with(|| {
let min_balance = <Test as Config>::Currency::minimum_balance();
Expand Down
21 changes: 14 additions & 7 deletions frame/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ type BalanceOf<T> =
type CodeVec<T> = BoundedVec<u8, <T as Config>::MaxCodeLen>;
type RelaxedCodeVec<T> = WeakBoundedVec<u8, <T as Config>::MaxCodeLen>;
type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
type DebugBufferVec<T> = BoundedVec<u8, <T as Config>::MaxDebugBufferLen>;

/// Used as a sentinel value when reading and writing contract memory.
///
Expand Down Expand Up @@ -344,6 +345,10 @@ pub mod pallet {
/// Do **not** set to `true` on productions chains.
#[pallet::constant]
type UnsafeUnstableInterface: Get<bool>;

/// The maximum length of the debug buffer in bytes.
#[pallet::constant]
type MaxDebugBufferLen: Get<u32>;
}

#[pallet::hooks]
Expand Down Expand Up @@ -952,7 +957,7 @@ where
debug: bool,
determinism: Determinism,
) -> ContractExecResult<BalanceOf<T>> {
let mut debug_message = if debug { Some(Vec::new()) } else { None };
let mut debug_message = if debug { Some(DebugBufferVec::<T>::default()) } else { None };
let output = Self::internal_call(
origin,
dest,
Expand All @@ -968,7 +973,7 @@ where
gas_consumed: output.gas_meter.gas_consumed(),
gas_required: output.gas_meter.gas_required(),
storage_deposit: output.storage_deposit,
debug_message: debug_message.unwrap_or_default(),
debug_message: debug_message.unwrap_or_default().to_vec(),
}
}

Expand All @@ -994,7 +999,7 @@ where
salt: Vec<u8>,
debug: bool,
) -> ContractInstantiateResult<T::AccountId, BalanceOf<T>> {
let mut debug_message = if debug { Some(Vec::new()) } else { None };
let mut debug_message = if debug { Some(DebugBufferVec::<T>::default()) } else { None };
let output = Self::internal_instantiate(
origin,
value,
Expand All @@ -1013,7 +1018,7 @@ where
gas_consumed: output.gas_meter.gas_consumed(),
gas_required: output.gas_meter.gas_required(),
storage_deposit: output.storage_deposit,
debug_message: debug_message.unwrap_or_default(),
debug_message: debug_message.unwrap_or_default().to_vec(),
}
}

Expand Down Expand Up @@ -1104,7 +1109,7 @@ where
gas_limit: Weight,
storage_deposit_limit: Option<BalanceOf<T>>,
data: Vec<u8>,
debug_message: Option<&mut Vec<u8>>,
debug_message: Option<&mut DebugBufferVec<T>>,
determinism: Determinism,
) -> InternalCallOutput<T> {
let mut gas_meter = GasMeter::new(gas_limit);
Expand Down Expand Up @@ -1147,7 +1152,7 @@ where
code: Code<CodeHash<T>>,
data: Vec<u8>,
salt: Vec<u8>,
mut debug_message: Option<&mut Vec<u8>>,
mut debug_message: Option<&mut DebugBufferVec<T>>,
) -> InternalInstantiateOutput<T> {
let mut storage_deposit = Default::default();
let mut gas_meter = GasMeter::new(gas_limit);
Expand All @@ -1163,7 +1168,9 @@ where
TryInstantiate::Skip,
)
.map_err(|(err, msg)| {
debug_message.as_mut().map(|buffer| buffer.extend(msg.as_bytes()));
debug_message
.as_mut()
.map(|buffer| buffer.try_append(&mut msg.as_bytes().to_vec()));
err
})?;
// The open deposit will be charged during execution when the
Expand Down
1 change: 1 addition & 0 deletions frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ impl Config for Test {
type MaxCodeLen = ConstU32<{ 128 * 1024 }>;
type MaxStorageKeyLen = ConstU32<128>;
type UnsafeUnstableInterface = UnstableInterface;
type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>;
}

pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]);
Expand Down