radix_engine/utils/
package_extractor.rs1use crate::internal_prelude::*;
2use crate::system::system_modules::costing::SystemLoanFeeReserve;
3use crate::vm::wasm::*;
4use crate::vm::wasm_runtime::NoOpWasmRuntime;
5use crate::vm::ScryptoVmVersion;
6use crate::{errors::InvokeError, transaction::CostingParameters};
7use radix_engine_interface::blueprints::package::*;
8use radix_transactions::prelude::TransactionCostingParameters;
9use sbor::rust::iter;
10
11#[derive(Debug)]
12pub enum ExtractSchemaError {
13 InvalidWasm(PrepareError),
14 RunSchemaGenError(InvokeError<WasmRuntimeError>),
15 SchemaDecodeError(DecodeError),
16}
17
18impl From<PrepareError> for ExtractSchemaError {
19 fn from(value: PrepareError) -> Self {
20 ExtractSchemaError::InvalidWasm(value)
21 }
22}
23
24pub fn extract_definition(code: &[u8]) -> Result<PackageDefinition, ExtractSchemaError> {
25 let function_exports = WasmModule::init(code)
26 .and_then(WasmModule::to_bytes)?
27 .1
28 .into_iter()
29 .filter(|s| s.ends_with("_schema"));
30
31 let validator = ScryptoV1WasmValidator::new(ScryptoVmVersion::latest());
33 let code_hash = CodeHash(Hash([0u8; 32]));
34 let instrumented_code = validator
35 .validate(&code, iter::empty())
36 .map_err(|e| ExtractSchemaError::InvalidWasm(e))?
37 .0;
38
39 let wasm_engine = DefaultWasmEngine::default();
41 let fee_reserve = SystemLoanFeeReserve::new(
42 CostingParameters::babylon_genesis(),
43 TransactionCostingParameters {
44 tip: Default::default(),
45 free_credit_in_xrd: Decimal::try_from(PREVIEW_CREDIT_IN_XRD).unwrap(),
46 },
47 false,
48 );
49 let mut wasm_execution_units_consumed = 0;
50 let mut runtime: Box<dyn WasmRuntime> = Box::new(NoOpWasmRuntime::new(
51 fee_reserve,
52 &mut wasm_execution_units_consumed,
53 ));
54 let mut instance = wasm_engine.instantiate(code_hash, &instrumented_code);
55 let mut blueprints = index_map_new();
56 for function_export in function_exports {
57 let rtn = instance
58 .invoke_export(&function_export, vec![], &mut runtime)
59 .map_err(ExtractSchemaError::RunSchemaGenError)?;
60
61 let name = function_export.replace("_schema", "").to_string();
62 let blueprint_setup: BlueprintDefinitionInit =
63 scrypto_decode(rtn.as_slice()).map_err(ExtractSchemaError::SchemaDecodeError)?;
64 blueprints.insert(name.clone(), blueprint_setup);
65 }
66
67 Ok(PackageDefinition { blueprints })
68}