util.rs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::time::SystemTime;
  19. use log::error;
  20. use wasmer::{FunctionEnvMut, WasmPtr};
  21. use crate::runtime::vm_runtime::{ContractSection, Env};
  22. /// Host function for logging strings.
  23. /// This is injected into the runtime with wasmer's `imports!` macro.
  24. pub(crate) fn drk_log(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) {
  25. let env = ctx.data();
  26. let memory_view = env.memory_view(&ctx);
  27. match ptr.read_utf8_string(&memory_view, len) {
  28. Ok(msg) => {
  29. let mut logs = env.logs.borrow_mut();
  30. logs.push(msg);
  31. std::mem::drop(logs);
  32. }
  33. Err(_) => {
  34. error!(target: "runtime::util", "Failed to read UTF-8 string from VM memory");
  35. }
  36. }
  37. }
  38. pub(crate) fn set_return_data(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i64 {
  39. let env = ctx.data();
  40. match env.contract_section {
  41. ContractSection::Exec | ContractSection::Metadata => {
  42. let memory_view = env.memory_view(&ctx);
  43. let Ok(slice) = ptr.slice(&memory_view, len) else {
  44. return darkfi_sdk::error::INTERNAL_ERROR
  45. };
  46. let Ok(return_data) = slice.read_to_vec() else {
  47. return darkfi_sdk::error::INTERNAL_ERROR
  48. };
  49. // This function should only ever be called once on the runtime.
  50. if env.contract_return_data.take().is_some() {
  51. return darkfi_sdk::error::SET_RETVAL_ERROR
  52. }
  53. env.contract_return_data.set(Some(return_data));
  54. 0
  55. }
  56. _ => darkfi_sdk::error::CALLER_ACCESS_DENIED,
  57. }
  58. }
  59. pub(crate) fn put_object_bytes(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i64 {
  60. let env = ctx.data();
  61. let memory_view = env.memory_view(&ctx);
  62. //debug!(target: "runtime::util", "diagnostic:");
  63. //let pages = memory_view.size().0;
  64. //debug!(target: "runtime::util", " pages: {}", pages);
  65. let Ok(slice) = ptr.slice(&memory_view, len) else {
  66. error!(target: "runtime::util", "Failed to make slice from ptr");
  67. return -2
  68. };
  69. let mut buf = vec![0_u8; len as usize];
  70. if let Err(e) = slice.read_slice(&mut buf) {
  71. error!(target: "runtime::util", "Failed to read from memory slice: {}", e);
  72. return -2
  73. };
  74. // There would be a serious problem if this is zero.
  75. // The number of pages is calculated as a quantity X + 1 where X >= 0
  76. //assert!(pages > 0);
  77. //debug!(target: "runtime::util", " memory: {:02x?}", &buf[0..32]);
  78. //debug!(target: "runtime::util", " {:x?}", &buf[32..64]);
  79. //debug!(target: "runtime::util", " ptr location: {}", ptr.offset());
  80. let mut objects = env.objects.borrow_mut();
  81. objects.push(buf);
  82. let obj_idx = objects.len() - 1;
  83. obj_idx as i64
  84. }
  85. pub(crate) fn get_object_bytes(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, idx: u32) -> i64 {
  86. // Get the slice, where we will read the size of the buffer
  87. let env = ctx.data();
  88. let memory_view = env.memory_view(&ctx);
  89. // Get the object from env
  90. let objects = env.objects.borrow();
  91. if idx as usize >= objects.len() {
  92. error!(target: "runtime::util", "Tried to access object out of bounds");
  93. return -5
  94. }
  95. let obj = &objects[idx as usize];
  96. // Read N bytes from the object and write onto the ptr.
  97. // We need to re-read the slice, since in the first run, we just read n
  98. let Ok(slice) = ptr.slice(&memory_view, obj.len() as u32) else {
  99. error!(target: "runtime::util", "Failed to make slice from ptr");
  100. return -2
  101. };
  102. // Put the result in the VM
  103. if let Err(e) = slice.write_slice(obj) {
  104. error!(target: "runtime::util", "Failed to write to memory slice: {}", e);
  105. return -4
  106. };
  107. 0
  108. }
  109. pub(crate) fn get_object_size(ctx: FunctionEnvMut<Env>, idx: u32) -> i64 {
  110. // Get the slice, where we will read the size of the buffer
  111. let env = ctx.data();
  112. //let memory_view = env.memory_view(&ctx);
  113. // Get the object from env
  114. let objects = env.objects.borrow();
  115. if idx as usize >= objects.len() {
  116. error!(target: "runtime::util", "Tried to access object out of bounds");
  117. return -5
  118. }
  119. let obj = &objects[idx as usize];
  120. obj.len() as i64
  121. }
  122. pub(crate) fn get_system_time() -> i64 {
  123. match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
  124. Ok(t) => t.as_secs() as i64,
  125. Err(_) => -1,
  126. }
  127. }