mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-13 18:51:05 +00:00
@@ -11,4 +11,5 @@ polkavm = { workspace = true }
|
||||
parity-scale-codec = { workspace = true }
|
||||
revive-solidity = { path = "../solidity" }
|
||||
era-compiler-llvm-context = { path = "../llvm-context" }
|
||||
alloy-primitives = { workspace = true }
|
||||
alloy-primitives = { workspace = true }
|
||||
alloy-sol-types = { workspace = true }
|
||||
|
||||
@@ -27,7 +27,8 @@ pub fn compile_blob(contract_name: &str, source_code: &str) -> Vec<u8> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use alloy_primitives::U256;
|
||||
use alloy_primitives::{FixedBytes, Keccak256, I256, U256};
|
||||
use alloy_sol_types::{sol, SolCall};
|
||||
|
||||
use crate::mock_runtime::{self, State};
|
||||
|
||||
@@ -46,6 +47,37 @@ mod tests {
|
||||
assert_eq!(state.storage[&U256::ZERO], U256::ZERO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_keccak_256() {
|
||||
sol!(
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
contract TestSha3 {
|
||||
function test(string memory _pre) external payable returns (bytes32);
|
||||
}
|
||||
);
|
||||
let source = r#"contract TestSha3 {
|
||||
function test(string memory _pre) external payable returns (bytes32 hash) {
|
||||
hash = keccak256(bytes(_pre));
|
||||
}
|
||||
}"#;
|
||||
let code = crate::compile_blob("TestSha3", source);
|
||||
|
||||
let param = "hello";
|
||||
let input = TestSha3::testCall::new((param.to_string(),)).abi_encode();
|
||||
|
||||
let state = State::new(input);
|
||||
let (instance, export) = mock_runtime::prepare(&code);
|
||||
let state = crate::mock_runtime::call(state, &instance, export);
|
||||
|
||||
assert_eq!(state.output.flags, 0);
|
||||
|
||||
let mut hasher = Keccak256::new();
|
||||
hasher.update(param);
|
||||
let expected = hasher.finalize();
|
||||
let received = FixedBytes::<32>::from_slice(&state.output.data);
|
||||
assert_eq!(expected, received);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn erc20() {
|
||||
let _ = crate::compile_blob("ERC20", include_str!("../contracts/ERC20.sol"));
|
||||
@@ -54,8 +86,8 @@ mod tests {
|
||||
#[test]
|
||||
fn triangle_number() {
|
||||
let code = crate::compile_blob("Computation", include_str!("../contracts/Computation.sol"));
|
||||
let param = alloy_primitives::U256::try_from(13).unwrap();
|
||||
let expected = alloy_primitives::U256::try_from(91).unwrap();
|
||||
let param = U256::try_from(13).unwrap();
|
||||
let expected = U256::try_from(91).unwrap();
|
||||
|
||||
// function triangle_number(int64)
|
||||
let mut input = 0x0f760610u32.to_be_bytes().to_vec();
|
||||
@@ -67,16 +99,15 @@ mod tests {
|
||||
|
||||
assert_eq!(state.output.flags, 0);
|
||||
|
||||
let received =
|
||||
alloy_primitives::U256::from_be_bytes::<32>(state.output.data.try_into().unwrap());
|
||||
let received = U256::from_be_bytes::<32>(state.output.data.try_into().unwrap());
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn odd_product() {
|
||||
let code = crate::compile_blob("Computation", include_str!("../contracts/Computation.sol"));
|
||||
let param = alloy_primitives::I256::try_from(5i32).unwrap();
|
||||
let expected = alloy_primitives::I256::try_from(945i64).unwrap();
|
||||
let param = I256::try_from(5i32).unwrap();
|
||||
let expected = I256::try_from(945i64).unwrap();
|
||||
|
||||
// function odd_product(int32)
|
||||
let mut input = 0x00261b66u32.to_be_bytes().to_vec();
|
||||
@@ -88,8 +119,7 @@ mod tests {
|
||||
|
||||
assert_eq!(state.output.flags, 0);
|
||||
|
||||
let received =
|
||||
alloy_primitives::I256::from_be_bytes::<32>(state.output.data.try_into().unwrap());
|
||||
let received = I256::from_be_bytes::<32>(state.output.data.try_into().unwrap());
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//! TODO: Switch to drink! once RISCV is ready in polkadot-sdk
|
||||
use std::collections::HashMap;
|
||||
|
||||
use alloy_primitives::U256;
|
||||
use alloy_primitives::{Keccak256, U256};
|
||||
use parity_scale_codec::Encode;
|
||||
use polkavm::{
|
||||
Caller, Config, Engine, ExportIndex, GasMeteringKind, InstancePre, Linker, Module,
|
||||
@@ -168,6 +168,27 @@ fn link_host_functions(engine: &Engine) -> Linker<State> {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
linker
|
||||
.func_wrap(
|
||||
"hash_keccak_256",
|
||||
|caller: Caller<State>,
|
||||
input_ptr: u32,
|
||||
input_len: u32,
|
||||
out_ptr: u32|
|
||||
-> Result<(), Trap> {
|
||||
let (mut caller, _) = caller.split();
|
||||
|
||||
let pre = caller.read_memory_into_vec(input_ptr, input_len)?;
|
||||
|
||||
let mut hasher = Keccak256::new();
|
||||
hasher.update(&pre);
|
||||
caller.write_memory(out_ptr, &hasher.finalize()[..])?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
linker
|
||||
}
|
||||
|
||||
|
||||
@@ -671,15 +671,13 @@ where
|
||||
"offset_ptrtoint",
|
||||
)?;
|
||||
let pointer_value = unsafe {
|
||||
self.builder
|
||||
.build_gep(
|
||||
self.byte_type(),
|
||||
heap_pointer.value.as_pointer_value(),
|
||||
&[offset],
|
||||
"heap_offset_via_gep",
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
self.builder.build_gep(
|
||||
self.byte_type(),
|
||||
heap_pointer.value.as_pointer_value(),
|
||||
&[offset],
|
||||
"heap_offset_via_gep",
|
||||
)
|
||||
}?;
|
||||
let value = self
|
||||
.builder()
|
||||
.build_load(pointer.r#type, pointer_value, name)?;
|
||||
@@ -806,6 +804,7 @@ where
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let value = self.build_byte_swap(value.as_basic_value_enum());
|
||||
|
||||
let instruction = self.builder.build_store(pointer_value, value).unwrap();
|
||||
|
||||
@@ -78,6 +78,7 @@ impl<'ctx> Pointer<'ctx> {
|
||||
"Stack pointers cannot be addressed"
|
||||
);
|
||||
|
||||
let offset = context.safe_truncate_int_to_i32(offset).unwrap();
|
||||
let value = context
|
||||
.builder
|
||||
.build_int_to_ptr(
|
||||
|
||||
@@ -59,29 +59,36 @@ pub fn copy<'ctx, D>(
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
// TODO: Untested
|
||||
let destination = Pointer::new_with_offset(
|
||||
context,
|
||||
AddressSpace::Heap,
|
||||
context.byte_type(),
|
||||
destination_offset,
|
||||
"calldata_copy_destination_pointer",
|
||||
);
|
||||
let heap_pointer = context
|
||||
.get_global(crate::eravm::GLOBAL_HEAP_MEMORY_POINTER)?
|
||||
.value
|
||||
.as_pointer_value();
|
||||
let destination = unsafe {
|
||||
context.builder().build_gep(
|
||||
context.byte_type(),
|
||||
heap_pointer,
|
||||
&[destination_offset],
|
||||
"calldata_pointer_with_offset",
|
||||
)
|
||||
}?;
|
||||
|
||||
let calldata_pointer = context
|
||||
.get_global(crate::eravm::GLOBAL_CALLDATA_POINTER)?
|
||||
.value
|
||||
.as_pointer_value();
|
||||
let source = context.build_gep(
|
||||
Pointer::new(context.byte_type(), AddressSpace::Stack, calldata_pointer),
|
||||
&[source_offset],
|
||||
context.field_type().as_basic_type_enum(),
|
||||
"calldata_pointer_with_offset",
|
||||
);
|
||||
let source = unsafe {
|
||||
context.builder().build_gep(
|
||||
context.byte_type(),
|
||||
calldata_pointer,
|
||||
&[source_offset],
|
||||
"calldata_pointer_with_offset",
|
||||
)
|
||||
}?;
|
||||
|
||||
context.build_memcpy(
|
||||
context.intrinsics().memory_copy_from_generic,
|
||||
destination,
|
||||
source,
|
||||
Pointer::new(context.byte_type(), AddressSpace::Stack, destination),
|
||||
Pointer::new(context.byte_type(), AddressSpace::Stack, source),
|
||||
size,
|
||||
"calldata_copy_memcpy_from_child",
|
||||
)
|
||||
|
||||
@@ -9,12 +9,52 @@ use crate::eravm::Dependency;
|
||||
/// Translates the `sha3` instruction.
|
||||
///
|
||||
pub fn sha3<'ctx, D>(
|
||||
_context: &mut Context<'ctx, D>,
|
||||
_offset: inkwell::values::IntValue<'ctx>,
|
||||
_length: inkwell::values::IntValue<'ctx>,
|
||||
context: &mut Context<'ctx, D>,
|
||||
offset: inkwell::values::IntValue<'ctx>,
|
||||
length: inkwell::values::IntValue<'ctx>,
|
||||
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
todo!()
|
||||
let offset_casted = context.safe_truncate_int_to_i32(offset)?;
|
||||
let heap_pointer = context.get_global(crate::eravm::GLOBAL_HEAP_MEMORY_POINTER)?;
|
||||
let input_pointer = unsafe {
|
||||
context.builder().build_gep(
|
||||
context.byte_type(),
|
||||
heap_pointer.value.as_pointer_value(),
|
||||
&[offset_casted],
|
||||
"heap_offset_via_gep",
|
||||
)
|
||||
}?;
|
||||
let input_pointer_casted = context.builder().build_ptr_to_int(
|
||||
input_pointer,
|
||||
context.integer_type(32),
|
||||
"input_pointer_casted",
|
||||
)?;
|
||||
|
||||
let length_casted = context.safe_truncate_int_to_i32(length)?;
|
||||
|
||||
let output_pointer = context.build_alloca(context.field_type(), "output_pointer");
|
||||
let output_pointer_casted = context.builder().build_ptr_to_int(
|
||||
output_pointer.value,
|
||||
context.integer_type(32),
|
||||
"output_pointer_casted",
|
||||
)?;
|
||||
|
||||
let function = context
|
||||
.module()
|
||||
.get_function("hash_keccak_256")
|
||||
.expect("is declared");
|
||||
|
||||
context.builder().build_call(
|
||||
function,
|
||||
&[
|
||||
input_pointer_casted.into(),
|
||||
length_casted.into(),
|
||||
output_pointer_casted.into(),
|
||||
],
|
||||
"call_seal_hash_keccak_256",
|
||||
)?;
|
||||
|
||||
Ok(context.build_byte_swap(context.build_load(output_pointer, "sha3_output")?))
|
||||
}
|
||||
|
||||
@@ -12,6 +12,15 @@ void * memset(void *b, int c, size_t len) {
|
||||
return b;
|
||||
}
|
||||
|
||||
void * memcpy(void *dst, const void *_src, size_t len) {
|
||||
uint8_t *dest = dst;
|
||||
const uint8_t *src = _src;
|
||||
|
||||
while (len--) *dest++ = *src++;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
// Exports
|
||||
|
||||
|
||||
Reference in New Issue
Block a user