1#![allow(unused_variables)]
16
17use crate::{
18 host::{CallFlags, HostFn, HostFnImpl, Result, StorageFlags},
19 pack_hi_lo, ReturnFlags,
20};
21use pallet_revive_proc_macro::unstable_hostfn;
22
23mod sys {
24 use crate::ReturnCode;
25
26 #[polkavm_derive::polkavm_define_abi]
27 mod abi {}
28
29 impl abi::FromHost for ReturnCode {
30 type Regs = (u64,);
31
32 fn from_host((a0,): Self::Regs) -> Self {
33 ReturnCode(a0 as _)
34 }
35 }
36
37 #[polkavm_derive::polkavm_import(abi = self::abi)]
38 extern "C" {
39 pub fn set_storage(
40 flags: u32,
41 key_ptr: *const u8,
42 key_len: u32,
43 value_ptr: *const u8,
44 value_len: u32,
45 ) -> ReturnCode;
46 pub fn clear_storage(flags: u32, key_ptr: *const u8, key_len: u32) -> ReturnCode;
47 pub fn get_storage(
48 flags: u32,
49 key_ptr: *const u8,
50 key_len: u32,
51 out_ptr: *mut u8,
52 out_len_ptr: *mut u32,
53 ) -> ReturnCode;
54 pub fn contains_storage(flags: u32, key_ptr: *const u8, key_len: u32) -> ReturnCode;
55 pub fn take_storage(
56 flags: u32,
57 key_ptr: *const u8,
58 key_len: u32,
59 out_ptr: *mut u8,
60 out_len_ptr: *mut u32,
61 ) -> ReturnCode;
62 pub fn call(
63 flags_and_callee: u64,
64 ref_time_limit: u64,
65 proof_size_limit: u64,
66 deposit_and_value: u64,
67 input_data: u64,
68 output_data: u64,
69 ) -> ReturnCode;
70 pub fn delegate_call(
71 flags_and_callee: u64,
72 ref_time_limit: u64,
73 proof_size_limit: u64,
74 deposit_ptr: *const u8,
75 input_data: u64,
76 output_data: u64,
77 ) -> ReturnCode;
78 pub fn instantiate(
79 ref_time_limit: u64,
80 proof_size_limit: u64,
81 deposit_and_value: u64,
82 input_data: u64,
83 output_data: u64,
84 address_and_salt: u64,
85 ) -> ReturnCode;
86 pub fn terminate(beneficiary_ptr: *const u8);
87 pub fn call_data_copy(out_ptr: *mut u8, out_len: u32, offset: u32);
88 pub fn call_data_load(out_ptr: *mut u8, offset: u32);
89 pub fn seal_return(flags: u32, data_ptr: *const u8, data_len: u32);
90 pub fn caller(out_ptr: *mut u8);
91 pub fn origin(out_ptr: *mut u8);
92 pub fn is_contract(account_ptr: *const u8) -> ReturnCode;
93 pub fn to_account_id(address_ptr: *const u8, out_ptr: *mut u8);
94 pub fn code_hash(address_ptr: *const u8, out_ptr: *mut u8);
95 pub fn code_size(address_ptr: *const u8) -> u64;
96 pub fn own_code_hash(out_ptr: *mut u8);
97 pub fn caller_is_origin() -> ReturnCode;
98 pub fn caller_is_root() -> ReturnCode;
99 pub fn address(out_ptr: *mut u8);
100 pub fn weight_to_fee(ref_time: u64, proof_size: u64, out_ptr: *mut u8);
101 pub fn weight_left(out_ptr: *mut u8, out_len_ptr: *mut u32);
102 pub fn ref_time_left() -> u64;
103 pub fn get_immutable_data(out_ptr: *mut u8, out_len_ptr: *mut u32);
104 pub fn set_immutable_data(ptr: *const u8, len: u32);
105 pub fn balance(out_ptr: *mut u8);
106 pub fn balance_of(addr_ptr: *const u8, out_ptr: *mut u8);
107 pub fn chain_id(out_ptr: *mut u8);
108 pub fn value_transferred(out_ptr: *mut u8);
109 pub fn now(out_ptr: *mut u8);
110 pub fn gas_limit() -> u64;
111 pub fn minimum_balance(out_ptr: *mut u8);
112 pub fn deposit_event(
113 topics_ptr: *const [u8; 32],
114 num_topic: u32,
115 data_ptr: *const u8,
116 data_len: u32,
117 );
118 pub fn gas_price() -> u64;
119 pub fn base_fee(out_ptr: *mut u8);
120 pub fn call_data_size() -> u64;
121 pub fn block_number(out_ptr: *mut u8);
122 pub fn block_hash(block_number_ptr: *const u8, out_ptr: *mut u8);
123 pub fn block_author(out_ptr: *mut u8);
124 pub fn hash_keccak_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8);
125 pub fn hash_blake2_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8);
126 pub fn hash_blake2_128(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8);
127 pub fn call_chain_extension(
128 id: u32,
129 input_ptr: *const u8,
130 input_len: u32,
131 out_ptr: *mut u8,
132 out_len_ptr: *mut u32,
133 ) -> ReturnCode;
134 pub fn call_runtime(call_ptr: *const u8, call_len: u32) -> ReturnCode;
135 pub fn sr25519_verify(
136 signature_ptr: *const u8,
137 pub_key_ptr: *const u8,
138 message_len: u32,
139 message_ptr: *const u8,
140 ) -> ReturnCode;
141 pub fn set_code_hash(code_hash_ptr: *const u8);
142 pub fn ecdsa_to_eth_address(key_ptr: *const u8, out_ptr: *mut u8) -> ReturnCode;
143 pub fn instantiation_nonce() -> u64;
144 pub fn xcm_execute(msg_ptr: *const u8, msg_len: u32) -> ReturnCode;
145 pub fn xcm_send(
146 dest_ptr: *const u8,
147 dest_len: *const u8,
148 msg_ptr: *const u8,
149 msg_len: u32,
150 out_ptr: *mut u8,
151 ) -> ReturnCode;
152 pub fn return_data_size() -> u64;
153 pub fn return_data_copy(out_ptr: *mut u8, out_len_ptr: *mut u32, offset: u32);
154 }
155}
156
157#[inline(always)]
158fn extract_from_slice(output: &mut &mut [u8], new_len: usize) {
159 debug_assert!(new_len <= output.len());
160 let tmp = core::mem::take(output);
161 *output = &mut tmp[..new_len];
162}
163
164#[inline(always)]
165fn ptr_len_or_sentinel(data: &mut Option<&mut &mut [u8]>) -> (*mut u8, u32) {
166 match data {
167 Some(ref mut data) => (data.as_mut_ptr(), data.len() as _),
168 None => (crate::SENTINEL as _, 0),
169 }
170}
171
172#[inline(always)]
173fn ptr_or_sentinel(data: &Option<&[u8; 32]>) -> *const u8 {
174 match data {
175 Some(ref data) => data.as_ptr(),
176 None => crate::SENTINEL as _,
177 }
178}
179
180impl HostFn for HostFnImpl {
181 fn instantiate(
182 ref_time_limit: u64,
183 proof_size_limit: u64,
184 deposit_limit: &[u8; 32],
185 value: &[u8; 32],
186 input: &[u8],
187 mut address: Option<&mut [u8; 20]>,
188 mut output: Option<&mut &mut [u8]>,
189 salt: Option<&[u8; 32]>,
190 ) -> Result {
191 let address = match address {
192 Some(ref mut data) => data.as_mut_ptr(),
193 None => crate::SENTINEL as _,
194 };
195 let (output_ptr, mut output_len_ptr) = ptr_len_or_sentinel(&mut output);
196 let deposit_limit_ptr = deposit_limit.as_ptr();
197 let salt_ptr = ptr_or_sentinel(&salt);
198
199 let deposit_and_value = pack_hi_lo(deposit_limit_ptr as _, value.as_ptr() as _);
200 let address_and_salt = pack_hi_lo(address as _, salt_ptr as _);
201 let input_data = pack_hi_lo(input.len() as _, input.as_ptr() as _);
202 let output_data = pack_hi_lo(&mut output_len_ptr as *mut _ as _, output_ptr as _);
203
204 let ret_code = unsafe {
205 sys::instantiate(
206 ref_time_limit,
207 proof_size_limit,
208 deposit_and_value,
209 input_data,
210 output_data,
211 address_and_salt,
212 )
213 };
214
215 if let Some(ref mut output) = output {
216 extract_from_slice(output, output_len_ptr as usize);
217 }
218
219 ret_code.into()
220 }
221
222 fn call(
223 flags: CallFlags,
224 callee: &[u8; 20],
225 ref_time_limit: u64,
226 proof_size_limit: u64,
227 deposit_limit: &[u8; 32],
228 value: &[u8; 32],
229 input: &[u8],
230 mut output: Option<&mut &mut [u8]>,
231 ) -> Result {
232 let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
233 let deposit_limit_ptr = deposit_limit.as_ptr();
234
235 let flags_and_callee = pack_hi_lo(flags.bits(), callee.as_ptr() as _);
236 let deposit_and_value = pack_hi_lo(deposit_limit_ptr as _, value.as_ptr() as _);
237 let input_data = pack_hi_lo(input.len() as _, input.as_ptr() as _);
238 let output_data = pack_hi_lo(&mut output_len as *mut _ as _, output_ptr as _);
239
240 let ret_code = unsafe {
241 sys::call(
242 flags_and_callee,
243 ref_time_limit,
244 proof_size_limit,
245 deposit_and_value,
246 input_data,
247 output_data,
248 )
249 };
250
251 if let Some(ref mut output) = output {
252 extract_from_slice(output, output_len as usize);
253 }
254
255 ret_code.into()
256 }
257
258 fn delegate_call(
259 flags: CallFlags,
260 address: &[u8; 20],
261 ref_time_limit: u64,
262 proof_size_limit: u64,
263 deposit_limit: &[u8; 32],
264 input: &[u8],
265 mut output: Option<&mut &mut [u8]>,
266 ) -> Result {
267 let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
268 let deposit_limit_ptr = deposit_limit.as_ptr();
269
270 let flags_and_callee = pack_hi_lo(flags.bits(), address.as_ptr() as u32);
271 let input_data = pack_hi_lo(input.len() as u32, input.as_ptr() as u32);
272 let output_data = pack_hi_lo(&mut output_len as *mut _ as u32, output_ptr as u32);
273
274 let ret_code = unsafe {
275 sys::delegate_call(
276 flags_and_callee,
277 ref_time_limit,
278 proof_size_limit,
279 deposit_limit_ptr as _,
280 input_data,
281 output_data,
282 )
283 };
284
285 if let Some(ref mut output) = output {
286 extract_from_slice(output, output_len as usize);
287 }
288
289 ret_code.into()
290 }
291
292 fn deposit_event(topics: &[[u8; 32]], data: &[u8]) {
293 unsafe {
294 sys::deposit_event(
295 topics.as_ptr(),
296 topics.len() as u32,
297 data.as_ptr(),
298 data.len() as u32,
299 )
300 }
301 }
302
303 fn set_storage(flags: StorageFlags, key: &[u8], encoded_value: &[u8]) -> Option<u32> {
304 let ret_code = unsafe {
305 sys::set_storage(
306 flags.bits(),
307 key.as_ptr(),
308 key.len() as u32,
309 encoded_value.as_ptr(),
310 encoded_value.len() as u32,
311 )
312 };
313 ret_code.into()
314 }
315
316 fn get_storage(flags: StorageFlags, key: &[u8], output: &mut &mut [u8]) -> Result {
317 let mut output_len = output.len() as u32;
318 let ret_code = {
319 unsafe {
320 sys::get_storage(
321 flags.bits(),
322 key.as_ptr(),
323 key.len() as u32,
324 output.as_mut_ptr(),
325 &mut output_len,
326 )
327 }
328 };
329 extract_from_slice(output, output_len as usize);
330 ret_code.into()
331 }
332
333 fn call_data_load(out_ptr: &mut [u8; 32], offset: u32) {
334 unsafe { sys::call_data_load(out_ptr.as_mut_ptr(), offset) };
335 }
336
337 fn gas_limit() -> u64 {
338 unsafe { sys::gas_limit() }
339 }
340
341 fn call_data_size() -> u64 {
342 unsafe { sys::call_data_size() }
343 }
344
345 fn return_value(flags: ReturnFlags, return_value: &[u8]) -> ! {
346 unsafe { sys::seal_return(flags.bits(), return_value.as_ptr(), return_value.len() as u32) }
347 panic!("seal_return does not return");
348 }
349
350 fn gas_price() -> u64 {
351 unsafe { sys::gas_price() }
352 }
353
354 fn base_fee(output: &mut [u8; 32]) {
355 unsafe { sys::base_fee(output.as_mut_ptr()) }
356 }
357
358 fn balance(output: &mut [u8; 32]) {
359 unsafe { sys::balance(output.as_mut_ptr()) }
360 }
361
362 fn value_transferred(output: &mut [u8; 32]) {
363 unsafe { sys::value_transferred(output.as_mut_ptr()) }
364 }
365
366 fn now(output: &mut [u8; 32]) {
367 unsafe { sys::now(output.as_mut_ptr()) }
368 }
369
370 fn chain_id(output: &mut [u8; 32]) {
371 unsafe { sys::chain_id(output.as_mut_ptr()) }
372 }
373
374 fn address(output: &mut [u8; 20]) {
375 unsafe { sys::address(output.as_mut_ptr()) }
376 }
377
378 fn caller(output: &mut [u8; 20]) {
379 unsafe { sys::caller(output.as_mut_ptr()) }
380 }
381
382 fn origin(output: &mut [u8; 20]) {
383 unsafe { sys::origin(output.as_mut_ptr()) }
384 }
385
386 fn block_number(output: &mut [u8; 32]) {
387 unsafe { sys::block_number(output.as_mut_ptr()) }
388 }
389
390 fn block_author(output: &mut [u8; 20]) {
391 unsafe { sys::block_author(output.as_mut_ptr()) }
392 }
393
394 fn weight_to_fee(ref_time_limit: u64, proof_size_limit: u64, output: &mut [u8; 32]) {
395 unsafe { sys::weight_to_fee(ref_time_limit, proof_size_limit, output.as_mut_ptr()) };
396 }
397
398 fn hash_keccak_256(input: &[u8], output: &mut [u8; 32]) {
399 unsafe { sys::hash_keccak_256(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) }
400 }
401
402 fn get_immutable_data(output: &mut &mut [u8]) {
403 let mut output_len = output.len() as u32;
404 unsafe { sys::get_immutable_data(output.as_mut_ptr(), &mut output_len) };
405 extract_from_slice(output, output_len as usize);
406 }
407
408 fn set_immutable_data(data: &[u8]) {
409 unsafe { sys::set_immutable_data(data.as_ptr(), data.len() as u32) }
410 }
411
412 fn balance_of(address: &[u8; 20], output: &mut [u8; 32]) {
413 unsafe { sys::balance_of(address.as_ptr(), output.as_mut_ptr()) };
414 }
415
416 fn code_hash(address: &[u8; 20], output: &mut [u8; 32]) {
417 unsafe { sys::code_hash(address.as_ptr(), output.as_mut_ptr()) }
418 }
419
420 fn code_size(address: &[u8; 20]) -> u64 {
421 unsafe { sys::code_size(address.as_ptr()) }
422 }
423
424 fn return_data_size() -> u64 {
425 unsafe { sys::return_data_size() }
426 }
427
428 fn return_data_copy(output: &mut &mut [u8], offset: u32) {
429 let mut output_len = output.len() as u32;
430 {
431 unsafe { sys::return_data_copy(output.as_mut_ptr(), &mut output_len, offset) };
432 }
433 extract_from_slice(output, output_len as usize);
434 }
435
436 fn ref_time_left() -> u64 {
437 unsafe { sys::ref_time_left() }
438 }
439
440 #[unstable_hostfn]
441 fn to_account_id(address: &[u8; 20], output: &mut [u8]) {
442 unsafe { sys::to_account_id(address.as_ptr(), output.as_mut_ptr()) }
443 }
444
445 #[unstable_hostfn]
446 fn block_hash(block_number_ptr: &[u8; 32], output: &mut [u8; 32]) {
447 unsafe { sys::block_hash(block_number_ptr.as_ptr(), output.as_mut_ptr()) };
448 }
449
450 #[unstable_hostfn]
451 fn call_chain_extension(func_id: u32, input: &[u8], mut output: Option<&mut &mut [u8]>) -> u32 {
452 let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
453 let ret_code = {
454 unsafe {
455 sys::call_chain_extension(
456 func_id,
457 input.as_ptr(),
458 input.len() as u32,
459 output_ptr,
460 &mut output_len,
461 )
462 }
463 };
464
465 if let Some(ref mut output) = output {
466 extract_from_slice(output, output_len as usize);
467 }
468 ret_code.into_u32()
469 }
470
471 fn call_data_copy(output: &mut [u8], offset: u32) {
472 let len = output.len() as u32;
473 unsafe { sys::call_data_copy(output.as_mut_ptr(), len, offset) };
474 }
475
476 #[unstable_hostfn]
477 fn call_runtime(call: &[u8]) -> Result {
478 let ret_code = unsafe { sys::call_runtime(call.as_ptr(), call.len() as u32) };
479 ret_code.into()
480 }
481
482 #[unstable_hostfn]
483 fn caller_is_origin() -> bool {
484 let ret_val = unsafe { sys::caller_is_origin() };
485 ret_val.into_bool()
486 }
487
488 #[unstable_hostfn]
489 fn caller_is_root() -> bool {
490 let ret_val = unsafe { sys::caller_is_root() };
491 ret_val.into_bool()
492 }
493
494 #[unstable_hostfn]
495 fn clear_storage(flags: StorageFlags, key: &[u8]) -> Option<u32> {
496 let ret_code = unsafe { sys::clear_storage(flags.bits(), key.as_ptr(), key.len() as u32) };
497 ret_code.into()
498 }
499
500 #[unstable_hostfn]
501 fn contains_storage(flags: StorageFlags, key: &[u8]) -> Option<u32> {
502 let ret_code =
503 unsafe { sys::contains_storage(flags.bits(), key.as_ptr(), key.len() as u32) };
504 ret_code.into()
505 }
506
507 #[unstable_hostfn]
508 fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result {
509 let ret_code = unsafe { sys::ecdsa_to_eth_address(pubkey.as_ptr(), output.as_mut_ptr()) };
510 ret_code.into()
511 }
512
513 #[unstable_hostfn]
514 fn hash_blake2_256(input: &[u8], output: &mut [u8; 32]) {
515 unsafe { sys::hash_blake2_256(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) }
516 }
517
518 #[unstable_hostfn]
519 fn hash_blake2_128(input: &[u8], output: &mut [u8; 16]) {
520 unsafe { sys::hash_blake2_128(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) }
521 }
522
523 #[unstable_hostfn]
524 fn is_contract(address: &[u8; 20]) -> bool {
525 let ret_val = unsafe { sys::is_contract(address.as_ptr()) };
526 ret_val.into_bool()
527 }
528
529 #[unstable_hostfn]
530 fn minimum_balance(output: &mut [u8; 32]) {
531 unsafe { sys::minimum_balance(output.as_mut_ptr()) }
532 }
533
534 #[unstable_hostfn]
535 fn own_code_hash(output: &mut [u8; 32]) {
536 unsafe { sys::own_code_hash(output.as_mut_ptr()) }
537 }
538
539 #[unstable_hostfn]
540 fn set_code_hash(code_hash: &[u8; 32]) {
541 unsafe { sys::set_code_hash(code_hash.as_ptr()) }
542 }
543
544 #[unstable_hostfn]
545 fn sr25519_verify(signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> Result {
546 let ret_code = unsafe {
547 sys::sr25519_verify(
548 signature.as_ptr(),
549 pub_key.as_ptr(),
550 message.len() as u32,
551 message.as_ptr(),
552 )
553 };
554 ret_code.into()
555 }
556
557 #[unstable_hostfn]
558 fn take_storage(flags: StorageFlags, key: &[u8], output: &mut &mut [u8]) -> Result {
559 let mut output_len = output.len() as u32;
560 let ret_code = {
561 unsafe {
562 sys::take_storage(
563 flags.bits(),
564 key.as_ptr(),
565 key.len() as u32,
566 output.as_mut_ptr(),
567 &mut output_len,
568 )
569 }
570 };
571 extract_from_slice(output, output_len as usize);
572 ret_code.into()
573 }
574
575 #[unstable_hostfn]
576 fn terminate(beneficiary: &[u8; 20]) -> ! {
577 unsafe { sys::terminate(beneficiary.as_ptr()) }
578 panic!("terminate does not return");
579 }
580
581 #[unstable_hostfn]
582 fn weight_left(output: &mut &mut [u8]) {
583 let mut output_len = output.len() as u32;
584 unsafe { sys::weight_left(output.as_mut_ptr(), &mut output_len) }
585 extract_from_slice(output, output_len as usize)
586 }
587
588 #[unstable_hostfn]
589 fn xcm_execute(msg: &[u8]) -> Result {
590 let ret_code = unsafe { sys::xcm_execute(msg.as_ptr(), msg.len() as _) };
591 ret_code.into()
592 }
593
594 #[unstable_hostfn]
595 fn xcm_send(dest: &[u8], msg: &[u8], output: &mut [u8; 32]) -> Result {
596 let ret_code = unsafe {
597 sys::xcm_send(
598 dest.as_ptr(),
599 dest.len() as _,
600 msg.as_ptr(),
601 msg.len() as _,
602 output.as_mut_ptr(),
603 )
604 };
605 ret_code.into()
606 }
607}