use super::*;
use gear_core::{
pages::{PageNumber, PageU32Size, WasmPage},
program::MemoryInfix,
};
use gear_wasm_instrument::parity_wasm::{self, elements::*};
use sp_io::hashing::blake2_256;
use sp_runtime::traits::Zero;
use sp_std::borrow::ToOwned;
pub fn account<AccountId: Origin>(name: &'static str, index: u32, seed: u32) -> AccountId {
let entropy = (name, index, seed).using_encoded(blake2_256);
H256::from_slice(&entropy[..]).cast()
}
pub fn create_module(num_pages: WasmPage) -> parity_wasm::elements::Module {
parity_wasm::elements::Module::new(vec![
Section::Type(TypeSection::with_types(vec![Type::Function(
FunctionType::new(vec![], vec![]),
)])),
Section::Import(ImportSection::with_entries(vec![ImportEntry::new(
"env".into(),
"memory".into(),
External::Memory(MemoryType::new(num_pages.raw(), None)),
)])),
Section::Function(FunctionSection::with_entries(vec![Func::new(0)])),
Section::Export(ExportSection::with_entries(vec![ExportEntry::new(
"init".into(),
Internal::Function(0),
)])),
Section::Code(CodeSection::with_bodies(vec![FuncBody::new(
vec![],
Instructions::new(vec![Instruction::End]),
)])),
])
}
pub fn generate_wasm(num_pages: WasmPage) -> Result<Vec<u8>, &'static str> {
let module = create_module(num_pages);
let code = parity_wasm::serialize(module).map_err(|_| "Failed to serialize module")?;
Ok(code)
}
pub fn generate_wasm2(num_pages: WasmPage) -> Result<Vec<u8>, &'static str> {
let module = parity_wasm::elements::Module::new(vec![
Section::Type(TypeSection::with_types(vec![
Type::Function(FunctionType::new(
vec![ValueType::I32],
vec![ValueType::I32],
)),
Type::Function(FunctionType::new(vec![], vec![])),
])),
Section::Import(ImportSection::with_entries(vec![
ImportEntry::new(
"env".into(),
"memory".into(),
External::Memory(MemoryType::new(1_u32, None)),
),
ImportEntry::new("env".into(), "alloc".into(), External::Function(0_u32)),
])),
Section::Function(FunctionSection::with_entries(vec![
Func::new(1_u32),
Func::new(1_u32),
])),
Section::Export(ExportSection::with_entries(vec![
ExportEntry::new("init".into(), Internal::Function(1)),
ExportEntry::new("handle".into(), Internal::Function(2)),
])),
Section::Code(CodeSection::with_bodies(vec![
FuncBody::new(vec![], Instructions::new(vec![Instruction::End])),
FuncBody::new(
vec![Local::new(1, ValueType::I32)],
Instructions::new(vec![
Instruction::I32Const(num_pages.raw() as i32),
Instruction::Call(0),
Instruction::SetLocal(0),
Instruction::End,
]),
),
])),
]);
let code = parity_wasm::serialize(module).map_err(|_| "Failed to serialize module")?;
Ok(code)
}
pub fn generate_wasm3(payload: Vec<u8>) -> Result<Vec<u8>, &'static str> {
let mut module = create_module(1.into());
module
.insert_section(Section::Custom(CustomSection::new(
"zeroed_section".to_owned(),
payload,
)))
.unwrap();
let code = parity_wasm::serialize(module).map_err(|_| "Failed to serialize module")?;
Ok(code)
}
pub fn set_program<
ProgramStorage: super::ProgramStorage<BlockNumber = BlockNumber>,
BlockNumber: Zero + Copy + Saturating,
>(
program_id: ProgramId,
code: Vec<u8>,
static_pages: WasmPage,
) {
let code_id = CodeId::generate(&code).into_origin();
let allocations: BTreeSet<WasmPage> = static_pages.iter_from_zero().collect();
let persistent_pages_data: BTreeMap<GearPage, PageBuf> = allocations
.iter()
.flat_map(|p| p.to_pages_iter())
.map(|p| (p, PageBuf::new_zeroed()))
.collect();
let pages_with_data = persistent_pages_data.keys().copied().collect();
let memory_infix = MemoryInfix::new(1u32);
let program = ActiveProgram {
allocations,
pages_with_data,
code_hash: code_id,
code_exports: Default::default(),
static_pages,
state: ProgramState::Initialized,
gas_reservation_map: GasReservationMap::default(),
expiration_block: Zero::zero(),
memory_infix,
};
for (page, page_buf) in persistent_pages_data {
ProgramStorage::set_program_page_data(program_id, memory_infix, page, page_buf);
}
ProgramStorage::add_program(program_id, program)
.expect("benchmarking; program duplicates should not exist");
}