mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-04-22 04:27:58 +00:00
@@ -4,3 +4,5 @@
|
||||
.DS_Store
|
||||
/*.sol
|
||||
/*.yul
|
||||
/*.ll
|
||||
/*.s
|
||||
|
||||
Generated
+56
-1
@@ -55,6 +55,36 @@ dependencies = [
|
||||
"bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloy-sol-macro"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e86ec0a47740b20bc5613b8712d0d321d031c4efc58e9645af96085d5cccfc27"
|
||||
dependencies = [
|
||||
"const-hex",
|
||||
"dunce",
|
||||
"heck 0.4.1",
|
||||
"indexmap",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.52",
|
||||
"syn-solidity",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloy-sol-types"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad09ec5853fa700d12d778ad224dcdec636af424d29fad84fb9a2f16a5b0ef09"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-sol-macro",
|
||||
"const-hex",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.81"
|
||||
@@ -470,6 +500,12 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.16.9"
|
||||
@@ -711,6 +747,12 @@ dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
@@ -1378,6 +1420,7 @@ name = "revive-integration"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-sol-types",
|
||||
"era-compiler-llvm-context",
|
||||
"hex",
|
||||
"parity-scale-codec",
|
||||
@@ -1737,7 +1780,7 @@ version = "0.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"heck 0.3.3",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1772,6 +1815,18 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn-solidity"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb3d0961cd53c23ea94eeec56ba940f636f6394788976e9f16ca5ee0aca7464a"
|
||||
dependencies = [
|
||||
"paste",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
|
||||
@@ -31,6 +31,7 @@ polkavm-linker = { git = "https://github.com/koute/polkavm.git" }
|
||||
polkavm = { git = "https://github.com/koute/polkavm.git" }
|
||||
parity-scale-codec = "3.6"
|
||||
alloy-primitives = "0.6"
|
||||
alloy-sol-types = "0.6"
|
||||
|
||||
[workspace.dependencies.inkwell]
|
||||
git = "https://github.com/TheDan64/inkwell.git"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
YUL and EVM bytecode recompiler to LLVM, targetting RISC-V on PolkaVM.
|
||||
|
||||
Code bases of [frontend](https://github.com/matter-labs/era-compiler-solidity) and [code generator](https://github.com/matter-labs/era-compiler-llvm-context) are forked adapted from ZKSync `zksolc`.
|
||||
Code bases of [frontend](https://github.com/matter-labs/era-compiler-solidity) and [code generator](https://github.com/matter-labs/era-compiler-llvm-context) are forked and adapted from ZKSync `zksolc`.
|
||||
|
||||
# Status
|
||||
|
||||
@@ -12,8 +12,9 @@ Currently, primary goal of this codebase is to allow for benchmarks comparing pe
|
||||
|
||||
The project is in a very early PoC phase. Don't yet expect the produced code to be working nor to be correct for anything more than a basic flipper contract at the current stage.
|
||||
|
||||
- [ ] Efficient implementations of byte swaps, memset, memmove and the like
|
||||
- [ ] Efficient implementations of byte swaps, memset, memmove, mulmod and the like
|
||||
- [ ] Use `drink` for integration tests once we have 64bit support in PolkaVM
|
||||
- [ ] Use PolkaVM allocator for heap space
|
||||
- [ ] Exercice `schlau` and possibly `smart-bench` benchmark cases
|
||||
- [ ] Tests currently rely on the binary being in $PATH, which is very annoying and requires `cargo install` all the times
|
||||
- [ ] Define how to do deployments
|
||||
|
||||
@@ -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