Compare commits

..

32 Commits

Author SHA1 Message Date
Cyrill Leutwiler 952c5cc894 resolc-0.1.0-dev.7 (#143)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-20 14:33:08 +01:00
Cyrill Leutwiler d8752ec6b5 the basefee opcode (#142)
Signed-off-by: xermicus <cyrill@parity.io>
2024-12-19 18:59:10 +01:00
Cyrill Leutwiler 6ad846a285 the base fee opcode (#141)
Signed-off-by: xermicus <cyrill@parity.io>
2024-12-19 12:44:15 +01:00
Cyrill Leutwiler 3f9771f838 update and fix the linker (#140) 2024-12-18 23:11:06 +01:00
Cyrill Leutwiler 22070a824d the gas limit opcode (#139)
Signed-off-by: xermicus <cyrill@parity.io>
2024-12-18 20:31:42 +01:00
Cyrill Leutwiler d299dd1a19 change getters to register version (#138) 2024-12-18 17:56:37 +01:00
Cyrill Leutwiler 14a598e840 implement the gas opcode (#136) 2024-12-18 17:19:32 +01:00
Cyrill Leutwiler 55ec0988e8 fix the CI runner version (#137)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-18 17:03:29 +01:00
Cyrill Leutwiler 909de515c4 Allow arbitrary call data size (#135)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-18 14:04:46 +01:00
Sebastian Miasojed afe44ad21b JS: Fix encoding conversion from utf16 to utf8 (#131) 2024-12-11 09:23:02 +01:00
Cyrill Leutwiler 2cb8f82266 calls: supply max ref_time and proof_size limits (#133)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-10 16:31:44 +01:00
Cyrill Leutwiler 6f2f158ef1 fix new clippy lint (#132)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-10 15:24:25 +01:00
Cyrill Leutwiler 4e5482bad2 fix the commit sha in the version (#129)
Signed-off-by: xermicus <cyrill@parity.io>
2024-12-03 12:34:17 +01:00
Cyrill Leutwiler 0110258d81 release 0.1.0 dev.6 (#128) 2024-11-29 17:45:47 +01:00
Cyrill Leutwiler f0d9d44dce Implement the gasprice opcode (#127) 2024-11-29 17:14:27 +01:00
Cyrill Leutwiler 3f6cd115ee update warnings (#126)
Signed-off-by: xermicus <cyrill@parity.io>
2024-11-29 16:23:36 +01:00
Cyrill Leutwiler 7c00bbb0fc remove unneeded utils (#125)
Signed-off-by: xermicus <cyrill@parity.io>
2024-11-29 16:21:24 +01:00
Cyrill Leutwiler 423a494621 Switch target to 64bit and enable the zbb feature (#120) 2024-11-29 15:56:10 +01:00
Cyrill Leutwiler 08112e3449 Fix broken link in README.md 2024-11-29 10:39:42 +01:00
Jeeyong Um db6ca1fcfa Fix broken link to introduction in README.md (#124) 2024-11-29 10:38:09 +01:00
Sebastian Miasojed 54d154a73c Merge pull request #123 from smiasojed/web
Add web worker compatibility
2024-11-29 10:22:59 +01:00
dependabot[bot] 93f1deb6a5 Bump rustls from 0.23.17 to 0.23.18 (#121)
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.17 to 0.23.18.
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.17...v/0.23.18)

---
updated-dependencies:
- dependency-name: rustls
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-29 09:50:29 +01:00
Sebastian Miasojed 9a150b13f3 Remove hardcoded soljson 2024-11-28 16:54:27 +01:00
Sebastian Miasojed 677cef9c0f Remove comment 2024-11-27 15:30:49 +01:00
Sebastian Miasojed d25be523c1 Update deps 2024-11-27 15:28:04 +01:00
Sebastian Miasojed 6a4fd1e991 Add web worker compatibility 2024-11-27 15:17:26 +01:00
Sebastian Miasojed 81915ddbcb Merge pull request #122 from smiasojed/sync
Remove async JS calls
2024-11-27 14:03:26 +01:00
Sebastian Miasojed 0f25bac4bd Fix CI 2024-11-27 08:49:07 +01:00
Sebastian Miasojed 7d41495587 Fmt 2024-11-27 08:30:07 +01:00
Sebastian Miasojed d6d5acfcce Remove deps on solc 2024-11-26 22:35:18 +01:00
Sebastian Miasojed 130ac48bf0 Fix revive wasm CI 2024-11-26 22:11:26 +01:00
Sebastian Miasojed b65fa2e42c Remove async calls from revive 2024-11-26 22:03:57 +01:00
71 changed files with 1699 additions and 2263 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ env:
jobs:
build-revive-debian-x86:
name: debian-container-x86
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
+2 -3
View File
@@ -8,12 +8,12 @@ on:
env:
CARGO_TERM_COLOR: always
REVIVE_WASM_INSTALL_DIR: ${{ github.workspace }}/js/dist/revive-cjs
REVIVE_WASM_INSTALL_DIR: ${{ github.workspace }}/target/wasm32-unknown-emscripten/release
EMSCRIPTEN_VERSION: 3.1.64
jobs:
build-revive-wasm:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
defaults:
run:
shell: bash
@@ -75,6 +75,5 @@ jobs:
name: revive-wasm
path: |
${{ env.REVIVE_WASM_INSTALL_DIR }}/resolc.js
${{ env.REVIVE_WASM_INSTALL_DIR }}/worker.js
${{ env.REVIVE_WASM_INSTALL_DIR }}/resolc.wasm
retention-days: 1
+1 -1
View File
@@ -11,7 +11,7 @@ env:
jobs:
build-ubuntu-x86:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
+1 -2
View File
@@ -14,6 +14,5 @@ artifacts
tmp
package-lock.json
/*.html
/js/src/resolc.*
/js/dist/
/build
soljson.js
+39
View File
@@ -2,6 +2,45 @@
## Unreleased
## v0.1.0-dev.7
This is a development pre-release.
### Added
- Implement the `GASPRICE` opcode.
- Implement the `BASEFEE` opcode.
- Implement the `GASLIMIT` opcode.
### Changed
- The `GAS` opcode now returns the remaining `ref_time`.
- Contracts can now be supplied call data input of arbitrary size.
- Some syscalls now return the value in a register, slightly improving emitted contract code.
- Calls forward maximum weight limits instead of 0, anticipating a change in polkadot-sdk where weight limits of 0 no longer interprets as uncapped limit.
### Fixed
- A linker bug which was preventing certain contracts from linking with the PVM linker.
- JS: Fix encoding conversion from JS string (UTF-16) to UTF-8.
- The git commit hash slug is always displayed in the version string.
## v0.1.0-dev.6
This is a development pre-release.
# Added
- Implement the `BLOCKHASH` opcode.
- Implement delegate calls.
- Implement the `GASPRICE` opcode. Currently hard-coded to return `1`.
- The ELF shared object contract artifact is dumped into the debug output directory.
- Initial support for emitting debug info (opt in via the `-g` flag)
# Changed
- resolc now emits 64bit PolkaVM blobs, reducing contract code size and execution time.
- The RISC-V bit-manipulation target feature (`zbb`) is enabled.
# Fixed
- Compilation to Wasm (for usage in node and web browsers)
## v0.1.0-dev.5
This is development pre-release.
Generated
+1070 -1677
View File
File diff suppressed because it is too large Load Diff
+19 -18
View File
@@ -3,7 +3,7 @@ resolver = "2"
members = ["crates/*"]
[workspace.package]
version = "0.1.0-dev.5"
version = "0.1.0-dev.7"
authors = [
"Cyrill Leutwiler <cyrill@parity.io>",
"Parity Technologies <admin@parity.io>",
@@ -14,18 +14,18 @@ repository = "https://github.com/paritytech/revive"
rust-version = "1.80.0"
[workspace.dependencies]
revive-benchmarks = { version = "0.1.0-dev.5", path = "crates/benchmarks" }
revive-builtins = { version = "0.1.0-dev.5", path = "crates/builtins" }
revive-common = { version = "0.1.0-dev.5", path = "crates/common" }
revive-differential = { version = "0.1.0-dev.5", path = "crates/differential" }
revive-integration = { version = "0.1.0-dev.5", path = "crates/integration" }
revive-linker = { version = "0.1.0-dev.5", path = "crates/linker" }
lld-sys = { version = "0.1.0-dev.5", path = "crates/lld-sys" }
revive-llvm-context = { version = "0.1.0-dev.5", path = "crates/llvm-context" }
revive-runtime-api = { version = "0.1.0-dev.5", path = "crates/runtime-api" }
revive-runner = { version = "0.1.0-dev.5", path = "crates/runner" }
revive-solidity = { version = "0.1.0-dev.5", path = "crates/solidity" }
revive-stdlib = { version = "0.1.0-dev.5", path = "crates/stdlib" }
revive-benchmarks = { version = "0.1.0-dev.7", path = "crates/benchmarks" }
revive-builtins = { version = "0.1.0-dev.7", path = "crates/builtins" }
revive-common = { version = "0.1.0-dev.7", path = "crates/common" }
revive-differential = { version = "0.1.0-dev.7", path = "crates/differential" }
revive-integration = { version = "0.1.0-dev.7", path = "crates/integration" }
revive-linker = { version = "0.1.0-dev.7", path = "crates/linker" }
lld-sys = { version = "0.1.0-dev.7", path = "crates/lld-sys" }
revive-llvm-context = { version = "0.1.0-dev.7", path = "crates/llvm-context" }
revive-runtime-api = { version = "0.1.0-dev.7", path = "crates/runtime-api" }
revive-runner = { version = "0.1.0-dev.7", path = "crates/runner" }
revive-solidity = { version = "0.1.0-dev.7", path = "crates/solidity" }
revive-stdlib = { version = "0.1.0-dev.7", path = "crates/stdlib" }
hex = "0.4"
petgraph = "0.6"
@@ -51,10 +51,10 @@ path-slash = "0.2"
rayon = "1.8"
clap = { version = "4", default-features = false, features = ["derive"] }
rand = "0.8"
polkavm-common = "0.14"
polkavm-linker = "0.14"
polkavm-disassembler = "0.14"
polkavm = "0.14"
polkavm-common = "0.18"
polkavm-linker = "0.18"
polkavm-disassembler = "0.18"
polkavm = "0.18"
alloy-primitives = { version = "0.8", features = ["serde"] }
alloy-sol-types = "0.8"
alloy-genesis = "0.3"
@@ -63,11 +63,12 @@ env_logger = { version = "0.10.0", default-features = false }
serde_stacker = "0.1"
criterion = { version = "0.5", features = ["html_reports"] }
log = { version = "0.4" }
git2 = "0.19.0"
# polkadot-sdk and friends
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
scale-info = { version = "2.11.1", default-features = false }
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "0449b214accd0f0fbf7ea3e8f3a8d8b7f99445e4" }
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "243b751abbb94369bbd92c83d8ab159ddfc3c556" }
# llvm
[workspace.dependencies.inkwell]
+15 -13
View File
@@ -1,18 +1,21 @@
.PHONY: install format test test-solidity test-cli test-integration test-workspace clean docs docs-build
RUSTFLAGS_EMSCRIPTEN := \
-Clink-arg=-sEXPORTED_FUNCTIONS=_main,_free,_malloc \
-Clink-arg=-sNO_INVOKE_RUN \
-Clink-arg=-sEXIT_RUNTIME \
-Clink-arg=-sINITIAL_MEMORY=64MB \
-Clink-arg=-sTOTAL_MEMORY=3GB \
-Clink-arg=-sALLOW_MEMORY_GROWTH \
-Clink-arg=-sEXPORTED_RUNTIME_METHODS=FS,callMain,stringToNewUTF8,cwrap \
-Clink-arg=-sMODULARIZE \
-Clink-arg=-sEXPORT_ES6 \
-Clink-arg=-sEXPORT_NAME=createRevive \
-Clink-arg=--js-library=js/embed/soljson_interface.js \
-Clink-arg=--pre-js=js/embed/pre.js
-C link-arg=-sEXPORTED_FUNCTIONS=_main,_free,_malloc \
-C link-arg=-sNO_INVOKE_RUN=1 \
-C link-arg=-sEXIT_RUNTIME=1 \
-C link-arg=-sALLOW_MEMORY_GROWTH=1 \
-C link-arg=-sEXPORTED_RUNTIME_METHODS=FS,callMain,stringToNewUTF8 \
-C link-arg=-sMODULARIZE=1 \
-C link-arg=-sEXPORT_NAME=createRevive \
-C link-arg=-sWASM_ASYNC_COMPILATION=0 \
-C link-arg=-sDYNAMIC_EXECUTION=0 \
-C link-arg=-sALLOW_TABLE_GROWTH=1 \
-C link-arg=--js-library=js/embed/soljson_interface.js \
-C link-arg=--pre-js=js/embed/pre.js \
-C link-arg=-sNODEJS_CATCH_EXIT=0 \
-C link-arg=-sDISABLE_EXCEPTION_CATCHING=0 \
-C opt-level=3
install: install-bin install-npm
@@ -25,7 +28,6 @@ install-npm:
install-wasm:
RUSTFLAGS='$(RUSTFLAGS_EMSCRIPTEN)' cargo build --target wasm32-unknown-emscripten -p revive-solidity --release --no-default-features
npm install
npm run build:revive
# install-revive: Build and install to the directory specified in REVIVE_INSTALL_DIR
ifeq ($(origin REVIVE_INSTALL_DIR), undefined)
+10 -7
View File
@@ -1,11 +1,11 @@
![CI](https://github.com/paritytech/revive/actions/workflows/rust.yml/badge.svg)
[![Docs](https://img.shields.io/badge/Docs-contracts.polkadot.io-brightgreen.svg)](https://contracts.polakdot.io)
[![Docs](https://img.shields.io/badge/Docs-contracts.polkadot.io-brightgreen.svg)](https://contracts.polkadot.io)
# revive
YUL and EVM assembly recompiler to LLVM, targetting RISC-V on [PolkaVM](https://github.com/koute/polkavm).
Visit [contracts.polkadot.io](contracts.polkadot.io) to learn more about contracts on Polkadot!
Visit [contracts.polkadot.io](https://contracts.polkadot.io) to learn more about contracts on Polkadot!
## Status
@@ -17,6 +17,14 @@ Discussion around the development is hosted on the [Polkadot Forum](https://foru
`resolc` depends on the [solc](https://github.com/ethereum/solidity) binary installed on your system.
Building from source requires a compatible LLVM build.
### LLVM
`revive` requires a build of LLVM 18.1.4 or later with the RISC-V _embedded_ target, including `compiler-rt`. Use the provided [build-llvm.sh](build-llvm.sh) build script to compile a compatible LLVM build locally in `$PWD/llvm18.0` (don't forget to add that to `$PATH` afterwards).
### The `resolc` Solidity frontend
To install the `resolc` Solidity frontend executable:
```bash
@@ -25,11 +33,6 @@ export PATH=${PWD}/llvm18.0/bin:$PATH
make install-bin
resolc --version
```
### LLVM
`revive` requires a build of LLVM 18.1.4 or later including `compiler-rt`. Use the provided [build-llvm.sh](build-llvm.sh) build script to compile a compatible LLVM build locally in `$PWD/llvm18.0` (don't forget to add that to `$PATH` afterwards).
### Cross-compilation to WASM
Cross-compiles the Revive compiler to WASM for running it in a Node.js or browser environment.
+2 -1
View File
@@ -8,4 +8,5 @@ To create a new pre-release:
2. Push a release tag to `main`
3. Manually trigger the `Build revive-debian` action
4. Create a __pre-release__ from the tag and manually upload the build artifact generated by the action
5. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly
5. Manually upload `resolc.js` and `resolc.wasm` from the `build-revive-wasm` action artifacts.
6. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly
+28 -28
View File
@@ -17,56 +17,56 @@
| | `EVM` | `PVMInterpreter` |
|:--------|:------------------------|:-------------------------------- |
| **`0`** | `5.97 us` (✅ **1.00x**) | `27.04 us` (❌ *4.53x slower*) |
| **`0`** | `3.36 us` (✅ **1.00x**) | `11.84 us` (❌ *3.52x slower*) |
### OddPorduct
| | `EVM` | `PVMInterpreter` |
|:-------------|:--------------------------|:-------------------------------- |
| **`10000`** | `4.26 ms` (✅ **1.00x**) | `2.88 ms` ( **1.48x faster**) |
| **`100000`** | `42.37 ms` (✅ **1.00x**) | `28.35 ms` ( **1.49x faster**) |
| **`300000`** | `127.88 ms` (✅ **1.00x**) | `88.43 ms` ( **1.45x faster**) |
| | `EVM` | `PVMInterpreter` |
|:-------------|:-------------------------|:-------------------------------- |
| **`10000`** | `3.11 ms` (✅ **1.00x**) | `1.53 ms` (🚀 **2.03x faster**) |
| **`100000`** | `30.70 ms` (✅ **1.00x**) | `15.54 ms` (🚀 **1.98x faster**) |
| **`300000`** | `92.68 ms` (✅ **1.00x**) | `45.47 ms` (🚀 **2.04x faster**) |
### TriangleNumber
| | `EVM` | `PVMInterpreter` |
|:-------------|:--------------------------|:-------------------------------- |
| **`10000`** | `2.85 ms` (✅ **1.00x**) | `2.37 ms` ( **1.20x faster**) |
| **`100000`** | `27.85 ms` (✅ **1.00x**) | `23.01 ms` ( **1.21x faster**) |
| **`360000`** | `103.01 ms` (✅ **1.00x**) | `83.66 ms` ( **1.23x faster**) |
| | `EVM` | `PVMInterpreter` |
|:-------------|:-------------------------|:-------------------------------- |
| **`10000`** | `2.29 ms` (✅ **1.00x**) | `1.09 ms` (🚀 **2.11x faster**) |
| **`100000`** | `22.84 ms` (✅ **1.00x**) | `10.66 ms` (🚀 **2.14x faster**) |
| **`360000`** | `82.29 ms` (✅ **1.00x**) | `37.01 ms` (🚀 **2.22x faster**) |
### FibonacciRecursive
| | `EVM` | `PVMInterpreter` |
|:---------|:--------------------------|:--------------------------------- |
| **`12`** | `195.19 us` (✅ **1.00x**) | `333.53 us` (*1.71x slower*) |
| **`16`** | `1.22 ms` (✅ **1.00x**) | `1.97 ms` (❌ *1.62x slower*) |
| **`20`** | `8.14 ms` (✅ **1.00x**) | `13.20 ms` (*1.62x slower*) |
| **`24`** | `55.09 ms` (✅ **1.00x**) | `88.56 ms` (*1.61x slower*) |
| **`12`** | `135.67 us` (✅ **1.00x**) | `125.02 us` (**1.09x faster**) |
| **`16`** | `903.75 us` (✅ **1.00x**) | `762.79 us` (✅ **1.18x faster**) |
| **`20`** | `6.12 ms` (✅ **1.00x**) | `4.96 ms` (**1.23x faster**) |
| **`24`** | `42.05 ms` (✅ **1.00x**) | `33.86 ms` (**1.24x faster**) |
### FibonacciIterative
| | `EVM` | `PVMInterpreter` |
|:----------|:-------------------------|:--------------------------------- |
| **`64`** | `33.39 us` (✅ **1.00x**) | `86.02 us` (❌ *2.58x slower*) |
| **`128`** | `52.91 us` (✅ **1.00x**) | `126.38 us` (❌ *2.39x slower*) |
| **`256`** | `82.33 us` (✅ **1.00x**) | `208.74 us` (❌ *2.54x slower*) |
| | `EVM` | `PVMInterpreter` |
|:----------|:-------------------------|:-------------------------------- |
| **`64`** | `15.04 us` (✅ **1.00x**) | `29.45 us` (❌ *1.96x slower*) |
| **`128`** | `26.36 us` (✅ **1.00x**) | `42.19 us` (❌ *1.60x slower*) |
| **`256`** | `48.61 us` (✅ **1.00x**) | `65.71 us` (❌ *1.35x slower*) |
### FibonacciBinet
| | `EVM` | `PVMInterpreter` |
|:----------|:-------------------------|:--------------------------------- |
| **`64`** | `32.29 us` (✅ **1.00x**) | `161.75 us` (❌ *5.01x slower*) |
| **`128`** | `36.02 us` (✅ **1.00x**) | `172.59 us` (❌ *4.79x slower*) |
| **`256`** | `41.21 us` (✅ **1.00x**) | `185.30 us` (❌ *4.50x slower*) |
| | `EVM` | `PVMInterpreter` |
|:----------|:-------------------------|:-------------------------------- |
| **`64`** | `15.22 us` (✅ **1.00x**) | `41.46 us` (❌ *2.72x slower*) |
| **`128`** | `17.05 us` (✅ **1.00x**) | `42.84 us` (❌ *2.51x slower*) |
| **`256`** | `19.00 us` (✅ **1.00x**) | `44.36 us` (❌ *2.34x slower*) |
### SHA1
| | `EVM` | `PVMInterpreter` |
|:----------|:--------------------------|:--------------------------------- |
| **`1`** | `160.17 us` (✅ **1.00x**) | `403.46 us` (❌ *2.52x slower*) |
| **`64`** | `286.69 us` (✅ **1.00x**) | `479.79 us` (❌ *1.67x slower*) |
| **`512`** | `1.18 ms` (✅ **1.00x**) | `1.37 ms` (❌ *1.16x slower*) |
| **`1`** | `110.04 us` (✅ **1.00x**) | `216.11 us` (❌ *1.96x slower*) |
| **`64`** | `209.04 us` (✅ **1.00x**) | `309.48 us` (❌ *1.48x slower*) |
| **`512`** | `903.65 us` (✅ **1.00x**) | `980.49 us` (✅ **1.09x slower**) |
---
Made with [criterion-table](https://github.com/nu11ptr/criterion-table)
+1 -1
View File
@@ -46,7 +46,7 @@ fn group<'error, M>(c: &'error mut Criterion<M>, group_name: &str) -> BenchmarkG
where
M: Measurement,
{
return c.benchmark_group(group_name);
c.benchmark_group(group_name)
}
fn bench_baseline(c: &mut Criterion) {
-3
View File
@@ -8,7 +8,4 @@ authors.workspace = true
build = "build.rs"
description = "compiler builtins for the revive compiler"
[features]
riscv-64 = []
[dependencies]
-3
View File
@@ -1,8 +1,5 @@
use std::{env, fs, io::Read, path::Path, process::Command};
#[cfg(not(feature = "riscv-64"))]
pub const BUILTINS_ARCHIVE_FILE: &str = "libclang_rt.builtins-riscv32.a";
#[cfg(feature = "riscv-64")]
pub const BUILTINS_ARCHIVE_FILE: &str = "libclang_rt.builtins-riscv64.a";
fn main() {
-3
View File
@@ -13,9 +13,6 @@ description = "Shared constants of the revive compiler"
[lib]
doctest = false
[features]
riscv-64 = []
[dependencies]
anyhow = { workspace = true }
serde = { workspace = true, features = ["derive"] }
+8 -8
View File
@@ -1,10 +1,10 @@
{
"Baseline": 961,
"Computation": 4024,
"DivisionArithmetics": 31789,
"ERC20": 44214,
"Events": 1737,
"FibonacciIterative": 2929,
"Flipper": 3402,
"SHA1": 26003
"Baseline": 1110,
"Computation": 2389,
"DivisionArithmetics": 14822,
"ERC20": 23973,
"Events": 1605,
"FibonacciIterative": 2023,
"Flipper": 1989,
"SHA1": 17026
}
+31
View File
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
/* runner.json
{
"differential": false,
"actions": [
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "BaseFee"
}
}
}
},
{
"VerifyCall": {
"success": true
}
}
]
}
*/
contract BaseFee {
constructor() payable {
assert(block.basefee == 0);
}
}
+32
View File
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
/* runner.json
{
"differential": false,
"actions": [
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "GasLeft"
}
}
}
},
{
"VerifyCall": {
"success": true
}
}
]
}
*/
contract GasLeft {
constructor() payable {
assert(gasleft() > gasleft());
assert(gasleft() > 0 && gasleft() < 0xffffffffffffffff);
}
}
+31
View File
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
/* runner.json
{
"differential": false,
"actions": [
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "GasLimit"
}
}
}
},
{
"VerifyCall": {
"success": true
}
}
]
}
*/
contract GasLimit {
constructor() payable {
assert(block.gaslimit == 2000000000000);
}
}
+31
View File
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
/* runner.json
{
"differential": false,
"actions": [
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "GasPrice"
}
}
}
},
{
"VerifyCall": {
"success": true
}
}
]
}
*/
contract GasPrice {
constructor() payable {
assert(tx.gasprice == 1);
}
}
+4
View File
@@ -46,6 +46,10 @@ test_spec!(immutables, "Immutables", "Immutables.sol");
test_spec!(transaction, "Transaction", "Transaction.sol");
test_spec!(block_hash, "BlockHash", "BlockHash.sol");
test_spec!(delegate, "Delegate", "Delegate.sol");
test_spec!(gas_price, "GasPrice", "GasPrice.sol");
test_spec!(gas_left, "GasLeft", "GasLeft.sol");
test_spec!(gas_limit, "GasLimit", "GasLimit.sol");
test_spec!(base_fee, "BaseFee", "BaseFee.sol");
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
vec![Instantiate {
-3
View File
@@ -7,9 +7,6 @@ repository.workspace = true
authors.workspace = true
description = "revive compiler linker utils"
[features]
riscv-64 = []
[dependencies]
inkwell = { workspace = true }
tempfile = { workspace = true }
+1 -7
View File
@@ -8,14 +8,7 @@ SECTIONS {
.text : { KEEP(*(.text.polkavm_export)) *(.text .text.*) }
}"#;
#[cfg(not(feature = "riscv-64"))]
const BUILTINS_ARCHIVE_FILE: &str = "libclang_rt.builtins-riscv32.a";
#[cfg(feature = "riscv-64")]
const BUILTINS_ARCHIVE_FILE: &str = "libclang_rt.builtins-riscv64.a";
#[cfg(not(feature = "riscv-64"))]
const BUILTINS_LIB_NAME: &str = "clang_rt.builtins-riscv32";
#[cfg(feature = "riscv-64")]
const BUILTINS_LIB_NAME: &str = "clang_rt.builtins-riscv64";
fn invoke_lld(cmd_args: &[&str]) -> bool {
@@ -64,6 +57,7 @@ pub fn link<T: AsRef<[u8]>>(input: T) -> anyhow::Result<Vec<u8>> {
"--relocatable",
"--emit-relocs",
"--no-relax",
"--unique",
"--gc-sections",
"--library-path",
dir.path().to_str().expect("should be utf8"),
-9
View File
@@ -13,15 +13,6 @@ description = "Shared front end code of the revive PolkaVM compilers"
[lib]
doctest = false
[features]
riscv-zbb = []
riscv-64 = [
"revive-linker/riscv-64",
"revive-builtins/riscv-64",
"revive-runtime-api/riscv-64",
"revive-common/riscv-64",
]
[dependencies]
anyhow = { workspace = true }
semver = { workspace = true }
-1
View File
@@ -61,7 +61,6 @@ pub use self::polkavm::evm::return_data as polkavm_evm_return_data;
pub use self::polkavm::evm::storage as polkavm_evm_storage;
pub use self::polkavm::metadata_hash::MetadataHash as PolkaVMMetadataHash;
pub use self::polkavm::r#const as polkavm_const;
pub use self::polkavm::utils as polkavm_utils;
pub use self::polkavm::Dependency as PolkaVMDependency;
pub use self::polkavm::DummyDependency as PolkaVMDummyDependency;
pub use self::polkavm::DummyLLVMWritable as PolkaVMDummyLLVMWritable;
+1 -4
View File
@@ -3,15 +3,12 @@
/// The LLVM framework version.
pub const LLVM_VERSION: semver::Version = semver::Version::new(18, 1, 4);
/// The register width sized type
/// The pointer width sized type.
pub static XLEN: usize = revive_common::BIT_LENGTH_X32;
/// The heap memory pointer pointer global variable name.
pub static GLOBAL_HEAP_MEMORY_POINTER: &str = "memory_pointer";
/// The calldata pointer global variable name.
pub static GLOBAL_CALLDATA_POINTER: &str = "ptr_calldata";
/// The calldata size global variable name.
pub static GLOBAL_CALLDATA_SIZE: &str = "calldatasize";
@@ -13,7 +13,7 @@ pub struct EVMLAData<'ctx> {
pub stack: Vec<Argument<'ctx>>,
}
impl<'ctx> EVMLAData<'ctx> {
impl EVMLAData<'_> {
/// The default stack size.
pub const DEFAULT_STACK_SIZE: usize = 64;
@@ -18,23 +18,12 @@ impl Entry {
/// The call flags argument index.
pub const ARGUMENT_INDEX_CALL_FLAGS: usize = 0;
/// Reserve 1kb for calldata.
pub const MAX_CALLDATA_SIZE: usize = 1024;
/// Initializes the global variables.
/// The pointers are not initialized, because it's not possible to create a null pointer.
pub fn initialize_globals<D>(context: &mut Context<D>) -> anyhow::Result<()>
where
D: Dependency + Clone,
{
let calldata_type = context.array_type(context.byte_type(), Self::MAX_CALLDATA_SIZE);
context.set_global(
crate::polkavm::GLOBAL_CALLDATA_POINTER,
calldata_type,
AddressSpace::Stack,
calldata_type.get_undef(),
);
context.set_global(
crate::polkavm::GLOBAL_HEAP_MEMORY_POINTER,
context.llvm().ptr_type(AddressSpace::Heap.into()),
@@ -53,9 +42,9 @@ impl Entry {
context.set_global(
crate::polkavm::GLOBAL_CALLDATA_SIZE,
context.word_type(),
context.xlen_type(),
AddressSpace::Stack,
context.word_undef(),
context.xlen_type().get_undef(),
);
context.set_global(
@@ -68,53 +57,22 @@ impl Entry {
Ok(())
}
/// Load the calldata via seal `input` and initialize the calldata end
/// and calldata size globals.
pub fn load_calldata<D>(context: &mut Context<D>) -> anyhow::Result<()>
/// Populate the calldata size global value.
pub fn load_calldata_size<D>(context: &mut Context<D>) -> anyhow::Result<()>
where
D: Dependency + Clone,
{
let input_pointer = context
.get_global(crate::polkavm::GLOBAL_CALLDATA_POINTER)?
let call_data_size_pointer = context
.get_global(crate::polkavm::GLOBAL_CALLDATA_SIZE)?
.value
.as_pointer_value();
let input_pointer_casted = context.builder.build_ptr_to_int(
input_pointer,
context.xlen_type(),
"input_pointer_casted",
)?;
let length_pointer = context.build_alloca_at_entry(context.xlen_type(), "len_ptr");
let length_pointer_casted = context.builder.build_ptr_to_int(
length_pointer.value,
context.xlen_type(),
"length_pointer_casted",
)?;
context.build_store(
length_pointer,
context.integer_const(crate::polkavm::XLEN, Self::MAX_CALLDATA_SIZE as u64),
)?;
context.build_runtime_call(
revive_runtime_api::polkavm_imports::INPUT,
&[input_pointer_casted.into(), length_pointer_casted.into()],
);
// Store the calldata size
let calldata_size = context
.build_load(length_pointer, "input_size")?
let call_data_size_value = context
.build_runtime_call(revive_runtime_api::polkavm_imports::CALL_DATA_SIZE, &[])
.expect("the call_data_size syscall method should return a value")
.into_int_value();
let calldata_size_casted = context.builder().build_int_z_extend(
calldata_size,
context.word_type(),
"zext_input_len",
)?;
context.set_global(
crate::polkavm::GLOBAL_CALLDATA_SIZE,
context.word_type(),
AddressSpace::Stack,
calldata_size_casted,
);
context
.builder()
.build_store(call_data_size_pointer, call_data_size_value)?;
Ok(())
}
@@ -220,7 +178,7 @@ where
context.set_basic_block(context.current_function().borrow().entry_block());
Self::initialize_globals(context)?;
Self::load_calldata(context)?;
Self::load_calldata_size(context)?;
Self::leave_entry(context)?;
context.build_unconditional_branch(context.current_function().borrow().return_block());
@@ -27,7 +27,7 @@ where
runtime::FUNCTION_LOAD_IMMUTABLE_DATA,
context.void_type().fn_type(Default::default(), false),
0,
Some(inkwell::module::Linkage::Private),
Some(inkwell::module::Linkage::External),
)?;
Ok(())
@@ -37,7 +37,7 @@ impl<'ctx> Global<'ctx> {
.add_global(r#type, Some(address_space.into()), name);
let global = Self { r#type, value };
global.value.set_linkage(inkwell::module::Linkage::Private);
global.value.set_linkage(inkwell::module::Linkage::External);
global
.value
.set_visibility(inkwell::GlobalVisibility::Default);
+15 -3
View File
@@ -165,8 +165,9 @@ where
fn link_immutable_data(&self, contract_path: &str) -> anyhow::Result<()> {
let size = self.solidity().immutables_size() as u32;
let exports = revive_runtime_api::immutable_data::module(self.llvm(), size);
self.module.link_in_module(exports).map_err(|error| {
let immutables = revive_runtime_api::immutable_data::module(self.llvm(), size);
self.module.link_in_module(immutables).map_err(|error| {
anyhow::anyhow!(
"The contract `{}` immutable data module linking error: {}",
contract_path,
@@ -202,6 +203,16 @@ where
);
}
/// Configure the revive datalayout.
fn set_data_layout(
llvm: &'ctx inkwell::context::Context,
module: &inkwell::module::Module<'ctx>,
) {
let source_module = revive_stdlib::module(llvm, "revive_stdlib").unwrap();
let data_layout = source_module.get_data_layout();
module.set_data_layout(&data_layout);
}
/// Initializes a new LLVM context.
pub fn new(
llvm: &'ctx inkwell::context::Context,
@@ -211,6 +222,7 @@ where
include_metadata_hash: bool,
debug_config: DebugConfig,
) -> Self {
Self::set_data_layout(llvm, &module);
Self::link_stdlib_module(llvm, &module);
Self::link_polkavm_imports(llvm, &module);
Self::set_polkavm_stack_size(llvm, &module, Self::POLKAVM_STACK_SIZE);
@@ -261,7 +273,7 @@ where
self.link_immutable_data(contract_path)?;
let target_machine = TargetMachine::new(Target::PVM, self.optimizer.settings())?;
target_machine.set_target_data(self.module());
self.module().set_triple(&target_machine.get_triple());
self.debug_config
.dump_llvm_ir_unoptimized(contract_path, self.module())?;
+10 -6
View File
@@ -60,8 +60,8 @@ where
let arguments = &[
flags.as_basic_value_enum(),
address_pointer.value.as_basic_value_enum(),
context.integer_const(64, 0).as_basic_value_enum(),
context.integer_const(64, 0).as_basic_value_enum(),
context.integer_const(64, u64::MAX).as_basic_value_enum(),
context.integer_const(64, u64::MAX).as_basic_value_enum(),
context.sentinel_pointer().value.as_basic_value_enum(),
value_pointer.value.as_basic_value_enum(),
input_pointer.value.as_basic_value_enum(),
@@ -90,7 +90,7 @@ where
let is_success = context.builder().build_int_compare(
inkwell::IntPredicate::EQ,
success,
context.xlen_type().const_zero(),
context.integer_const(revive_common::BIT_LENGTH_X64, 0),
"is_success",
)?;
@@ -139,8 +139,12 @@ where
let arguments = &[
flags.as_basic_value_enum(),
address_pointer.value.as_basic_value_enum(),
context.integer_const(64, 0).as_basic_value_enum(),
context.integer_const(64, 0).as_basic_value_enum(),
context
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(),
context
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(),
context.sentinel_pointer().value.as_basic_value_enum(),
input_pointer.value.as_basic_value_enum(),
input_length.as_basic_value_enum(),
@@ -168,7 +172,7 @@ where
let is_success = context.builder().build_int_compare(
inkwell::IntPredicate::EQ,
success,
context.xlen_type().const_zero(),
context.integer_const(revive_common::BIT_LENGTH_X64, 0),
"is_success",
)?;
+27 -29
View File
@@ -1,10 +1,7 @@
//! Translates the calldata instructions.
use crate::polkavm::context::address_space::AddressSpace;
use crate::polkavm::context::pointer::Pointer;
use crate::polkavm::context::Context;
use crate::polkavm::Dependency;
use inkwell::types::BasicType;
/// Translates the calldata load.
pub fn load<'ctx, D>(
@@ -14,19 +11,15 @@ pub fn load<'ctx, D>(
where
D: Dependency + Clone,
{
let calldata_pointer = context
.get_global(crate::polkavm::GLOBAL_CALLDATA_POINTER)?
.value
.as_pointer_value();
let offset = context.build_gep(
Pointer::new(context.byte_type(), AddressSpace::Stack, calldata_pointer),
&[offset],
context.word_type().as_basic_type_enum(),
"calldata_pointer_with_offset",
let output_pointer = context.build_alloca_at_entry(context.word_type(), "call_data_output");
let offset = context.safe_truncate_int_to_xlen(offset)?;
context.build_runtime_call(
revive_runtime_api::polkavm_imports::CALL_DATA_LOAD,
&[output_pointer.to_int(context).into(), offset.into()],
);
context
.build_load(offset, "calldata_value")
.and_then(|value| context.build_byte_swap(value))
context.build_load(output_pointer, "call_data_load_value")
}
/// Translates the calldata size.
@@ -37,8 +30,14 @@ where
D: Dependency + Clone,
{
let value = context.get_global_value(crate::polkavm::GLOBAL_CALLDATA_SIZE)?;
Ok(value)
Ok(context
.builder()
.build_int_z_extend(
value.into_int_value(),
context.word_type(),
"call_data_size_value",
)?
.into())
}
/// Translates the calldata copy.
@@ -51,20 +50,19 @@ pub fn copy<'ctx, D>(
where
D: Dependency + Clone,
{
let offset = context.safe_truncate_int_to_xlen(destination_offset)?;
let source_offset = context.safe_truncate_int_to_xlen(source_offset)?;
let size = context.safe_truncate_int_to_xlen(size)?;
let destination = context.build_heap_gep(offset, size)?;
let destination_offset = context.safe_truncate_int_to_xlen(destination_offset)?;
let output_pointer = context.build_heap_gep(destination_offset, size)?;
let calldata_pointer = context
.get_global(crate::polkavm::GLOBAL_CALLDATA_POINTER)?
.value
.as_pointer_value();
let source = context.build_gep(
Pointer::new(context.byte_type(), AddressSpace::Stack, calldata_pointer),
&[context.safe_truncate_int_to_xlen(source_offset)?],
context.byte_type(),
"calldata_pointer_with_offset",
context.build_runtime_call(
revive_runtime_api::polkavm_imports::CALL_DATA_COPY,
&[
output_pointer.to_int(context).into(),
size.into(),
source_offset.into(),
],
);
context.build_memcpy(destination, source, size, "calldata_copy_memcpy_from_child")
Ok(())
}
+21 -5
View File
@@ -7,22 +7,38 @@ use crate::polkavm::Dependency;
/// Translates the `gas_limit` instruction.
pub fn gas_limit<'ctx, D>(
_context: &mut Context<'ctx, D>,
context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
where
D: Dependency + Clone,
{
todo!()
let gas_limit_value = context
.build_runtime_call(revive_runtime_api::polkavm_imports::GAS_LIMIT, &[])
.expect("the gas_limit syscall method should return a value")
.into_int_value();
Ok(context
.builder()
.build_int_z_extend(gas_limit_value, context.word_type(), "gas_limit")?
.into())
}
/// Translates the `gas_price` instruction.
pub fn gas_price<'ctx, D>(
_context: &mut Context<'ctx, D>,
context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
where
D: Dependency + Clone,
{
todo!()
let gas_price_value = context
.build_runtime_call(revive_runtime_api::polkavm_imports::GAS_PRICE, &[])
.expect("the gas_price syscall method should return a value")
.into_int_value();
Ok(context
.builder()
.build_int_z_extend(gas_price_value, context.word_type(), "gas_price")?
.into())
}
/// Translates the `tx.origin` instruction.
@@ -121,7 +137,7 @@ pub fn basefee<'ctx, D>(
where
D: Dependency + Clone,
{
Ok(context.word_const(0).as_basic_value_enum())
context.build_runtime_call_to_getter(revive_runtime_api::polkavm_imports::BASE_FEE)
}
/// Translates the `address` instruction.
@@ -1,7 +1,5 @@
//! Translates the value and balance operations.
use inkwell::values::BasicValue;
use crate::polkavm::context::Context;
use crate::polkavm::Dependency;
@@ -12,7 +10,15 @@ pub fn gas<'ctx, D>(
where
D: Dependency + Clone,
{
Ok(context.integer_const(256, 0).as_basic_value_enum())
let ref_time_left_value = context
.build_runtime_call(revive_runtime_api::polkavm_imports::REF_TIME_LEFT, &[])
.expect("the ref_time_left syscall method should return a value")
.into_int_value();
Ok(context
.builder()
.build_int_z_extend(ref_time_left_value, context.word_type(), "gas_left")?
.into())
}
/// Translates the `value` instruction.
+11 -10
View File
@@ -16,19 +16,20 @@ where
Some(address) => address,
None => super::context::address(context)?.into_int_value(),
};
let address_pointer = context.build_address_argument_store(address)?;
let output_pointer = context.build_alloca_at_entry(context.word_type(), "output_pointer");
context.build_runtime_call(
revive_runtime_api::polkavm_imports::CODE_SIZE,
&[
address_pointer.to_int(context).into(),
output_pointer.to_int(context).into(),
],
);
let code_size_value = context
.build_runtime_call(
revive_runtime_api::polkavm_imports::CODE_SIZE,
&[address_pointer.to_int(context).into()],
)
.expect("the code_size syscall method should return a value")
.into_int_value();
context.build_load(output_pointer, "code_size")
Ok(context
.builder()
.build_int_z_extend(code_size_value, context.word_type(), "code_size")?
.into())
}
/// Translates the `extcodehash` instruction.
@@ -10,17 +10,19 @@ pub fn size<'ctx, D>(
where
D: Dependency + Clone,
{
let output_pointer = context.build_alloca_at_entry(context.word_type(), "return_data_size");
let output_pointer_parameter = context.builder().build_ptr_to_int(
output_pointer.value,
context.xlen_type(),
"return_data_copy_output_pointer",
)?;
context.build_runtime_call(
revive_runtime_api::polkavm_imports::RETURNDATASIZE,
&[output_pointer_parameter.into()],
);
context.build_load(output_pointer, "return_data_size_load")
let return_data_size_value = context
.build_runtime_call(revive_runtime_api::polkavm_imports::RETURNDATASIZE, &[])
.expect("the return_data_size syscall method should return a value")
.into_int_value();
Ok(context
.builder()
.build_int_z_extend(
return_data_size_value,
context.word_type(),
"return_data_size",
)?
.into())
}
/// Translates the return data copy, trapping if
+2 -3
View File
@@ -4,10 +4,8 @@ pub mod r#const;
pub mod context;
pub mod evm;
pub mod metadata_hash;
pub mod utils;
pub use self::r#const::*;
use self::utils::keccak256;
use crate::debug_config::DebugConfig;
use crate::optimizer::settings::Settings as OptimizerSettings;
@@ -15,6 +13,7 @@ use crate::optimizer::settings::Settings as OptimizerSettings;
use anyhow::Context as AnyhowContext;
use polkavm_common::program::ProgramBlob;
use polkavm_disassembler::{Disassembler, DisassemblyFormat};
use sha3::Digest;
use self::context::build::Build;
use self::context::Context;
@@ -55,7 +54,7 @@ pub fn build_assembly_text(
assembly_text.to_owned(),
metadata_hash,
bytecode.to_owned(),
keccak256(bytecode),
hex::encode(sha3::Keccak256::digest(bytecode)),
))
}
-60
View File
@@ -1,60 +0,0 @@
//! Some LLVM IR generator utilies.
use crate::polkavm::context::Context;
use crate::polkavm::Dependency;
/// Clamps `value` to `max_value`, if `value` is bigger than `max_value`.
pub fn clamp<'ctx, D>(
context: &mut Context<'ctx, D>,
value: inkwell::values::IntValue<'ctx>,
max_value: inkwell::values::IntValue<'ctx>,
name: &str,
) -> anyhow::Result<inkwell::values::IntValue<'ctx>>
where
D: Dependency + Clone,
{
let in_bounds_block = context.append_basic_block(format!("{name}_is_bounds_block").as_str());
let join_block = context.append_basic_block(format!("{name}_join_block").as_str());
let pointer = context.build_alloca(context.word_type(), format!("{name}_pointer").as_str());
context.build_store(pointer, max_value)?;
let is_in_bounds = context.builder().build_int_compare(
inkwell::IntPredicate::ULE,
value,
max_value,
format!("{name}_is_in_bounds").as_str(),
)?;
context.build_conditional_branch(is_in_bounds, in_bounds_block, join_block)?;
context.set_basic_block(in_bounds_block);
context.build_store(pointer, value)?;
context.build_unconditional_branch(join_block);
context.set_basic_block(join_block);
let result = context.build_load(pointer, name)?;
Ok(result.into_int_value())
}
/// Computes the `keccak256` hash for `preimage`.
pub fn keccak256(preimage: &[u8]) -> String {
use sha3::Digest;
let hash_bytes = sha3::Keccak256::digest(preimage);
hash_bytes
.into_iter()
.map(|byte| format!("{byte:02x}"))
.collect::<Vec<String>>()
.join("")
}
#[cfg(test)]
mod tests {
#[test]
fn keccak256() {
assert_eq!(
super::keccak256("zksync".as_bytes()),
"0238fb1ab06c28c32885f9a4842207ac480c2467df26b6c58e201679628c5a5b"
);
}
}
+2 -20
View File
@@ -20,28 +20,16 @@ pub struct TargetMachine {
impl TargetMachine {
/// The LLVM target name.
#[cfg(not(feature = "riscv-64"))]
pub const VM_TARGET_NAME: &'static str = "riscv32";
#[cfg(feature = "riscv-64")]
pub const VM_TARGET_NAME: &'static str = "riscv64";
/// The LLVM target triple.
#[cfg(not(feature = "riscv-64"))]
pub const VM_TARGET_TRIPLE: &'static str = "riscv32-unknown-unknown-elf";
#[cfg(feature = "riscv-64")]
pub const VM_TARGET_TRIPLE: &'static str = "riscv64-unknown-unknown-elf";
/// The LLVM target cpu
#[cfg(not(feature = "riscv-64"))]
pub const VM_TARGET_CPU: &'static str = "generic-rv32";
#[cfg(feature = "riscv-64")]
pub const VM_TARGET_CPU: &'static str = "generic-rv64";
/// LLVM target features.
#[cfg(feature = "riscv-zbb")]
pub const VM_FEATURES: &'static str = "+zbb,+a,+e,+m,+c,+fast-unaligned-access,+xtheadcondmov";
#[cfg(not(feature = "riscv-zbb"))]
pub const VM_FEATURES: &'static str = "+a,+e,+m,+c,+fast-unaligned-access,+xtheadcondmov";
pub const VM_FEATURES: &'static str =
"+e,+m,+a,+c,+zbb,+auipc-addi-fusion,+ld-add-fusion,+lui-addi-fusion,+xtheadcondmov";
/// A shortcut constructor.
/// A separate instance for every optimization level is created.
@@ -70,12 +58,6 @@ impl TargetMachine {
})
}
/// Sets the target-specific data in the module.
pub fn set_target_data(&self, module: &inkwell::module::Module) {
module.set_triple(&self.target_machine.get_triple());
module.set_data_layout(&self.target_machine.get_target_data().get_data_layout());
}
/// Writes the LLVM module to a memory buffer.
pub fn write_to_memory_buffer(
&self,
@@ -13,9 +13,6 @@ impl Target {
/// Returns the target name.
pub fn name(&self) -> &str {
match self {
#[cfg(not(feature = "riscv-64"))]
Self::PVM => "riscv32",
#[cfg(feature = "riscv-64")]
Self::PVM => "riscv64",
}
}
@@ -23,9 +20,6 @@ impl Target {
/// Returns the target triple.
pub fn triple(&self) -> &str {
match self {
#[cfg(not(feature = "riscv-64"))]
Self::PVM => "riscv32-unknown-unknown-elf",
#[cfg(feature = "riscv-64")]
Self::PVM => "riscv64-unknown-unknown-elf",
}
}
@@ -43,9 +37,6 @@ impl FromStr for Target {
fn from_str(string: &str) -> Result<Self, Self::Err> {
match string {
#[cfg(not(feature = "riscv-64"))]
"riscv32" => Ok(Self::PVM),
#[cfg(feature = "riscv-64")]
"riscv64" => Ok(Self::PVM),
_ => Err(anyhow::anyhow!(
"Unknown target `{}`. Supported targets: {:?}",
@@ -59,9 +50,6 @@ impl FromStr for Target {
impl std::fmt::Display for Target {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
#[cfg(not(feature = "riscv-64"))]
Target::PVM => write!(f, "riscv32"),
#[cfg(feature = "riscv-64")]
Target::PVM => write!(f, "riscv64"),
}
}
Binary file not shown.
+1 -1
View File
@@ -55,7 +55,7 @@ pub const BOB: H160 = H160([2u8; 20]);
/// The charlie test account
pub const CHARLIE: H160 = H160([3u8; 20]);
/// Default gas limit
pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024);
pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000_000, 3 * 1024 * 1024 * 1024);
/// Default deposit limit
pub const DEPOSIT_LIMIT: Balance = 10_000_000;
+6 -1
View File
@@ -1,4 +1,4 @@
use frame_support::runtime;
use frame_support::{runtime, weights::constants::WEIGHT_REF_TIME_PER_SECOND};
use pallet_revive::AccountId32Mapper;
use polkadot_sdk::*;
@@ -46,6 +46,7 @@ mod runtime {
#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
impl frame_system::Config for Runtime {
type Block = Block;
type BlockWeights = BlockWeights;
type AccountId = AccountId32;
type AccountData = pallet_balances::AccountData<<Runtime as pallet_balances::Config>::Balance>;
}
@@ -65,6 +66,10 @@ parameter_types! {
pub const DepositPerByte: Balance = 1;
pub const DepositPerItem: Balance = 2;
pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0);
pub BlockWeights: frame_system::limits::BlockWeights =
frame_system::limits::BlockWeights::simple_max(
Weight::from_parts(2u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX),
);
}
#[derive_impl(pallet_revive::config_preludes::TestDefaultConfig)]
+2 -2
View File
@@ -421,7 +421,7 @@ impl Specs {
origin,
value,
gas_limit.unwrap_or(GAS_LIMIT),
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT),
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
code,
data,
salt.0,
@@ -461,7 +461,7 @@ impl Specs {
dest.to_eth_addr(&results),
value,
gas_limit.unwrap_or(GAS_LIMIT),
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT),
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
data,
DebugInfo::Skip,
CollectEvents::Skip,
-3
View File
@@ -7,9 +7,6 @@ repository.workspace = true
authors.workspace = true
description = "Implements the low level runtime API bindings with pallet contracts"
[features]
riscv-64 = []
[dependencies]
anyhow = { workspace = true }
inkwell = { workspace = true, features = ["target-riscv", "no-libffi-linking", "llvm18-0"] }
-15
View File
@@ -1,23 +1,8 @@
use std::{env, fs, path::Path, process::Command};
#[cfg(not(feature = "riscv-64"))]
const TARGET_TRIPLE_FLAG: &str = "-triple=riscv32-unknown-unknown-elf";
#[cfg(feature = "riscv-64")]
const TARGET_TRIPLE_FLAG: &str = "-triple=riscv64-unknown-unknown-elf";
#[cfg(not(feature = "riscv-64"))]
const TARGET_FLAG: &str = "--target=riscv32";
#[cfg(feature = "riscv-64")]
const TARGET_FLAG: &str = "--target=riscv64";
#[cfg(not(feature = "riscv-64"))]
const TARGET_ARCH_FLAG: &str = "-march=rv32emac";
#[cfg(feature = "riscv-64")]
const TARGET_ARCH_FLAG: &str = "-march=rv64emac";
#[cfg(not(feature = "riscv-64"))]
const TARGET_ABI_FLAG: &str = "-mabi=ilp32e";
#[cfg(feature = "riscv-64")]
const TARGET_ABI_FLAG: &str = "-mabi=lp64e";
const IMPORTS_SOUCE: &str = "src/polkavm_imports.c";
+22 -22
View File
@@ -52,29 +52,29 @@ pub fn instantiate(context: &Context) -> StructType {
context.struct_type(
&[
// code_hash_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// ref_time_limit: u64,
context.i64_type().as_basic_type_enum(),
// proof_size_limit: u64,
context.i64_type().as_basic_type_enum(),
// deposit_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// value_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// input_data_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// input_data_len: u32,
context.i32_type().as_basic_type_enum(),
// address_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// output_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// output_len_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// salt_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
],
true,
false,
)
}
@@ -85,25 +85,25 @@ pub fn call(context: &Context) -> StructType {
// flags: u32,
context.i32_type().as_basic_type_enum(),
// address_ptr:
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// ref_time_limit: u64,
context.i64_type().as_basic_type_enum(),
// proof_size_limit: u64,
context.i64_type().as_basic_type_enum(),
// deposit_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// value_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// input_data_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// input_data_len: u32,
context.i32_type().as_basic_type_enum(),
// output_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// output_len_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
],
true,
false,
)
}
@@ -114,22 +114,22 @@ pub fn delegate_call(context: &Context) -> StructType {
// flags: u32,
context.i32_type().as_basic_type_enum(),
// address_ptr:
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// ref_time_limit: u64,
context.i64_type().as_basic_type_enum(),
// proof_size_limit: u64,
context.i64_type().as_basic_type_enum(),
// deposit_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// input_data_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// input_data_len: u32,
context.i32_type().as_basic_type_enum(),
// output_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
// output_len_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
context.i32_type().as_basic_type_enum(),
],
true,
false,
)
}
+23 -9
View File
@@ -70,33 +70,43 @@ POLKAVM_IMPORT(void, balance, uint32_t)
POLKAVM_IMPORT(void, balance_of, uint32_t, uint32_t)
POLKAVM_IMPORT(void, base_fee, uint32_t)
POLKAVM_IMPORT(void, block_hash, uint32_t, uint32_t)
POLKAVM_IMPORT(void, block_number, uint32_t)
POLKAVM_IMPORT(uint32_t, call, uint32_t)
POLKAVM_IMPORT(uint64_t, call, uint32_t)
POLKAVM_IMPORT(uint32_t, delegate_call, uint32_t)
POLKAVM_IMPORT(uint64_t, call_data_copy, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, call_data_load, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, call_data_size)
POLKAVM_IMPORT(void, caller, uint32_t)
POLKAVM_IMPORT(void, chain_id, uint32_t)
POLKAVM_IMPORT(uint32_t, code_size, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, code_size, uint32_t)
POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, delegate_call, uint32_t)
POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, gas_limit);
POLKAVM_IMPORT(uint64_t, gas_price);
POLKAVM_IMPORT(void, get_immutable_data, uint32_t, uint32_t);
POLKAVM_IMPORT(uint32_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, input, uint32_t, uint32_t)
POLKAVM_IMPORT(uint32_t, instantiate, uint32_t)
POLKAVM_IMPORT(uint64_t, instantiate, uint32_t)
POLKAVM_IMPORT(void, now, uint32_t)
@@ -104,12 +114,16 @@ POLKAVM_IMPORT(void, origin, uint32_t)
POLKAVM_IMPORT(void, seal_return, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint32_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, ref_time_left)
POLKAVM_IMPORT(void, return_data_copy, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, return_data_size, uint32_t)
POLKAVM_IMPORT(uint64_t, return_data_size)
POLKAVM_IMPORT(void, set_immutable_data, uint32_t, uint32_t);
POLKAVM_IMPORT(uint64_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, value_transferred, uint32_t)
POLKAVM_IMPORT(void, weight_to_fee, uint64_t, uint64_t, uint32_t);
+29 -8
View File
@@ -20,13 +20,19 @@ pub static BALANCE: &str = "balance";
pub static BALANCE_OF: &str = "balance_of";
pub static BASE_FEE: &str = "base_fee";
pub static BLOCK_HASH: &str = "block_hash";
pub static BLOCK_NUMBER: &str = "block_number";
pub static CALL: &str = "call";
pub static DELEGATE_CALL: &str = "delegate_call";
pub static CALL_DATA_COPY: &str = "call_data_copy";
pub static CALL_DATA_LOAD: &str = "call_data_load";
pub static CALL_DATA_SIZE: &str = "call_data_size";
pub static CALLER: &str = "caller";
@@ -36,25 +42,29 @@ pub static CODE_SIZE: &str = "code_size";
pub static CODE_HASH: &str = "code_hash";
pub static DELEGATE_CALL: &str = "delegate_call";
pub static DEPOSIT_EVENT: &str = "deposit_event";
pub static GAS_LIMIT: &str = "gas_limit";
pub static GAS_PRICE: &str = "gas_price";
pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data";
pub static GET_STORAGE: &str = "get_storage";
pub static HASH_KECCAK_256: &str = "hash_keccak_256";
pub static INPUT: &str = "input";
pub static INSTANTIATE: &str = "instantiate";
pub static NOW: &str = "now";
pub static ORIGIN: &str = "origin";
pub static RETURN: &str = "seal_return";
pub static REF_TIME_LEFT: &str = "ref_time_left";
pub static SET_STORAGE: &str = "set_storage";
pub static RETURN: &str = "seal_return";
pub static RETURNDATACOPY: &str = "return_data_copy";
@@ -62,38 +72,49 @@ pub static RETURNDATASIZE: &str = "return_data_size";
pub static SET_IMMUTABLE_DATA: &str = "set_immutable_data";
pub static SET_STORAGE: &str = "set_storage";
pub static VALUE_TRANSFERRED: &str = "value_transferred";
pub static WEIGHT_TO_FEE: &str = "weight_to_fee";
/// All imported runtime API symbols.
/// Useful for configuring common attributes and linkage.
pub static IMPORTS: [&str; 27] = [
pub static IMPORTS: [&str; 34] = [
SBRK,
MEMORY_SIZE,
ADDRESS,
BALANCE,
BALANCE_OF,
BASE_FEE,
BLOCK_HASH,
BLOCK_NUMBER,
CALL,
DELEGATE_CALL,
CALL_DATA_COPY,
CALL_DATA_LOAD,
CALL_DATA_SIZE,
CALLER,
CHAIN_ID,
CODE_SIZE,
CODE_HASH,
DELEGATE_CALL,
DEPOSIT_EVENT,
GAS_LIMIT,
GAS_PRICE,
GET_IMMUTABLE_DATA,
GET_STORAGE,
HASH_KECCAK_256,
INPUT,
INSTANTIATE,
NOW,
ORIGIN,
REF_TIME_LEFT,
RETURN,
RETURNDATACOPY,
RETURNDATASIZE,
SET_IMMUTABLE_DATA,
SET_STORAGE,
VALUE_TRANSFERRED,
WEIGHT_TO_FEE,
];
/// Creates a LLVM module from the [BITCODE].
+3
View File
@@ -48,6 +48,9 @@ mimalloc = { version = "*", default-features = false }
libc = { workspace = true }
inkwell = { workspace = true, features = ["target-riscv", "llvm18-0-no-llvm-linking"]}
[build-dependencies]
git2 = { workspace = true }
[features]
parallel = ["rayon"]
default = ["parallel"]
+5 -7
View File
@@ -1,9 +1,7 @@
fn main() {
let git_rev = std::process::Command::new("git")
.args(["rev-parse", "--short", "HEAD"])
.output()
.map(|out| String::from_utf8(out.stdout).unwrap_or_default())
.unwrap_or("unknown".to_owned());
println!("cargo:rustc-env=GIT_COMMIT_HASH={}", git_rev.trim());
let repo = git2::Repository::open("../..").expect("should be a repository");
let head = repo.head().expect("should have head");
let commit = head.peel_to_commit().expect("should have commit");
let id = &commit.id().to_string()[..7];
println!("cargo:rustc-env=GIT_COMMIT_HASH={id}");
}
+2 -1
View File
@@ -8,6 +8,7 @@ use std::collections::HashSet;
use serde::Deserialize;
use serde::Serialize;
use sha3::Digest;
use crate::evmla::ethereal_ir::entry_link::EntryLink;
use crate::evmla::ethereal_ir::EtherealIR;
@@ -45,7 +46,7 @@ impl Assembly {
/// Gets the contract `keccak256` hash.
pub fn keccak256(&self) -> String {
let json = serde_json::to_vec(self).expect("Always valid");
revive_llvm_context::polkavm_utils::keccak256(json.as_slice())
hex::encode(sha3::Keccak256::digest(json.as_slice()))
}
/// Sets the full contract path.
@@ -1163,7 +1163,7 @@ where
self.name.as_str(),
function_type,
output_size,
Some(inkwell::module::Linkage::Private),
Some(inkwell::module::Linkage::External),
)?;
function
.borrow_mut()
@@ -35,10 +35,9 @@ impl Error {
let message = r#"
┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Warning: It looks like you are using 'ecrecover' to validate a signature of a user account. │
zkSync Era comes with native account abstraction support, therefore it is highly recommended NOT │
Polkadot comes with native account abstraction support, therefore it is highly recommended NOT
│ to rely on the fact that the account has an ECDSA private key attached to it since accounts might│
│ implement other signature schemes. │
│ Read more about Account Abstraction at https://v2-docs.zksync.io/dev/developer-guides/aa.html │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘"#
.to_owned();
@@ -109,10 +108,9 @@ impl Error {
let message = r#"
┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Warning: You are checking for 'tx.origin' in your code, which might lead to unexpected behavior. │
zkSync Era comes with native account abstraction support, and therefore the initiator of a │
Polkadot comes with native account abstraction support, and therefore the initiator of a
│ transaction might be different from the contract calling your code. It is highly recommended NOT │
│ to rely on tx.origin, but use msg.sender instead. │
│ Read more about Account Abstraction at https://v2-docs.zksync.io/dev/developer-guides/aa.html │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘"#
.to_owned();
@@ -202,8 +202,8 @@ pub enum Name {
/// size of memory, i.e. largest accessed memory index
MSize,
/// verbatim instruction with 0 inputs and 0 outputs
/// only works in the Yul mode, so it is mostly used as a tool for extending Yul for zkSync
/// verbatim instruction with 0 inputs and 0 outputs only works in the Yul mode,
/// so it is mostly used as a tool for extending Yul for PolkaVM
Verbatim {
/// the number of input arguments
input_size: usize,
@@ -211,7 +211,7 @@ where
self.identifier.as_str(),
function_type,
self.result.len(),
Some(inkwell::module::Linkage::Private),
Some(inkwell::module::Linkage::External),
)?;
revive_llvm_context::PolkaVMFunction::set_attributes(
context.llvm(),
+2 -2
View File
@@ -1,7 +1,7 @@
; Adapted from: https://github.com/matter-labs/era-compiler-llvm/blob/v1.4.0/llvm/lib/Target/EraVM/eravm-stdlib.ll
target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
target triple = "riscv32-unknown-unknown-elf"
target datalayout = "e-m:e-p:32:64-p1:32:64-i64:64-i128:128-n32:64-S64"
target triple = "riscv64-unknown-none-elf"
define i256 @__addmod(i256 %arg1, i256 %arg2, i256 %modulo) #4 {
entry:
+26 -21
View File
@@ -1,47 +1,52 @@
var Module = {
stdinData: "",
stdoutCallback: null,
stderrCallback: null,
stdinData: null,
stdinDataPosition: 0,
stdoutData: [],
stderrData: [],
// Function to set a callback for stdout
setStdoutCallback: function(callback) {
this.stdoutCallback = callback;
// Function to read and return all collected stdout data as a string
readFromStdout: function() {
if (!this.stdoutData.length) return "";
const decoder = new TextDecoder('utf-8');
const data = decoder.decode(new Uint8Array(this.stdoutData));
this.stdoutData = [];
return data;
},
// Function to set a callback for stderr
setStderrCallback: function(callback) {
this.stderrCallback = callback;
// Function to read and return all collected stderr data as a string
readFromStderr: function() {
if (!this.stderrData.length) return "";
const decoder = new TextDecoder('utf-8');
const data = decoder.decode(new Uint8Array(this.stderrData));
this.stderrData = [];
return data;
},
// Function to set input data for stdin
setStdinData: function(data) {
this.stdinData = data;
writeToStdin: function(data) {
const encoder = new TextEncoder();
this.stdinData = encoder.encode(data);
this.stdinDataPosition = 0;
},
// `preRun` is called before the program starts running
preRun: function() {
// Define a custom stdin function
function customStdin() {
if (Module.stdinData.length === 0) {
if (!Module.stdinData || Module.stdinDataPosition >= Module.stdinData.length) {
return null; // End of input (EOF)
}
const char = Module.stdinData.charCodeAt(0);
Module.stdinData = Module.stdinData.slice(1); // Remove the character from input
return char;
return Module.stdinData[Module.stdinDataPosition++];
}
// Define a custom stdout function
function customStdout(char) {
if (Module.stdoutCallback) {
Module.stdoutCallback(String.fromCharCode(char));
}
Module.stdoutData.push(char);
}
// Define a custom stderr function
function customStderr(char) {
if (Module.stderrCallback) {
Module.stderrCallback(String.fromCharCode(char));
}
Module.stderrData.push(char);
}
FS.init(customStdin, customStdout, customStderr);
+28 -46
View File
@@ -1,60 +1,42 @@
mergeInto(LibraryManager.library, {
soljson_compile: function(inputPtr, inputLen) {
const inputJson = UTF8ToString(inputPtr, inputLen);
const output = Module.solc.compile(inputJson)
return stringToNewUTF8(output)
const output = Module.soljson.cwrap('solidity_compile', 'string', ['string'])(inputJson);
return stringToNewUTF8(output);
},
soljson_version: function() {
var version = Module.solc.version();
return stringToNewUTF8(version)
const version = Module.soljson.cwrap("solidity_version", "string", [])();
return stringToNewUTF8(version);
},
resolc_compile: function(inputPtr, inputLen) {
const { Worker } = require('worker_threads');
const deasync = require('deasync');
const inputJson = UTF8ToString(inputPtr, inputLen);
var inputJson = UTF8ToString(inputPtr, inputLen);
function compileWithWorker(inputJson, callback) {
return new Promise((resolve, reject) => {
const worker = new Worker(new URL('./worker.js', import.meta.url), {
type: 'module',
});
// Listen for messages from the worker
worker.on('message', (message) => {
resolve(message.output); // Resolve the promise with the output
callback(null, message.output);
worker.terminate(); // Terminate the worker after processing
});
// Listen for errors from the worker
worker.on('error', (error) => {
reject(error);
callback(error);
worker.terminate();
});
// Send the input JSON to the worker
worker.postMessage(inputJson);
});
// Check if running in a web worker or node.js
if (typeof importScripts === 'function') {
// Running in a web worker
importScripts('./resolc.js');
var revive = createRevive()
} else if (typeof require === 'function') {
// Running in Node.js
const path = require('path');
createRevive = require(path.resolve(__dirname, './resolc.js'));
var revive = createRevive();
} else {
throw new Error('Unknown environment: Unable to load resolc.js');
}
let result = null;
let error = null;
revive.writeToStdin(inputJson);
// Use deasync to block until promise resolves
compileWithWorker(inputJson, function (err, res) {
error = err;
result = res;
});
// TODO: deasync is not present in browsers, another solution needs to be implemented
deasync.loopWhile(() => result === null && error === null);
// Call main on the new instance
const result = revive.callMain(['--recursive-process']);
if (error) {
const errorJson = JSON.stringify({ type: 'error', message: error.message || "Unknown error" });
return stringToNewUTF8(errorJson)
if (result) {
const stderrString = revive.readFromStderr();
const error = JSON.stringify({ type: 'error', message: stderrString || "Unknown error" });
return stringToNewUTF8(error);
} else {
const stdoutString = revive.readFromStdout();
const json = JSON.stringify({ type: 'success', data: stdoutString });
return stringToNewUTF8(json);
}
const resultJson = JSON.stringify({ type: 'success', data: result });
return stringToNewUTF8(resultJson);
},
});
+1
View File
@@ -0,0 +1 @@
../../../target/wasm32-unknown-emscripten/release/resolc.js
+1
View File
@@ -0,0 +1 @@
../../../target/wasm32-unknown-emscripten/release/resolc.wasm
@@ -1,6 +1,5 @@
import solc from 'solc';
// Import the Emscripten module
import createRevive from './dist/revive-esm/resolc.js';
const soljson = require('solc/soljson');
const createRevive = require('./resolc.js');
const compilerStandardJsonInput = {
language: 'Solidity',
@@ -31,30 +30,16 @@ const compilerStandardJsonInput = {
};
async function runCompiler() {
const m = await createRevive();
m.solc = solc;
const m = createRevive();
m.soljson = soljson;
// Set input data for stdin
m.setStdinData(JSON.stringify(compilerStandardJsonInput));
var stdoutString = "";
m.setStdoutCallback(function(char) {
if (char.charCodeAt(0) === '\n') {
console.log("new line")
exit
}
stdoutString += char;
});
var stderrString = "";
m.setStderrCallback(function(char) {
stderrString += char;
});
m.writeToStdin(JSON.stringify(compilerStandardJsonInput));
// Compile the Solidity source code
let x = m.callMain(['--standard-json']);
console.log("Stdout: " + stdoutString)
console.error("Stderr: " + stderrString)
console.log("Stdout: " + m.readFromStdout());
console.error("Stderr: " + m.readFromStderr());
}
runCompiler().catch(err => {
+35
View File
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Web Worker Example</title>
<style>
/* Ensure the pre tag wraps long lines */
pre {
white-space: pre-wrap; /* Wrap long lines */
word-wrap: break-word; /* Break long words */
max-width: 100%; /* Optional: Ensures it doesn't overflow container */
overflow-wrap: break-word; /* Another method for wrapping */
}
</style>
</head>
<body>
<h1>Revive Compilation Output</h1>
<pre id="output"></pre>
<script>
var outputElement = document.getElementById('output');
var worker = new Worker('./worker.js');
worker.addEventListener('message', function (e) {
const output = e.data.output
outputElement.textContent = output;
}, false);
worker.postMessage({
contractCode: 'contract C { function f() public { } }',
})
</script>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
../../../target/wasm32-unknown-emscripten/release/resolc.js
+1
View File
@@ -0,0 +1 @@
../../../target/wasm32-unknown-emscripten/release/resolc.wasm
+38
View File
@@ -0,0 +1,38 @@
importScripts('./soljson.js');
importScripts('./resolc.js');
// Handle messages from the main thread
onmessage = async function (e) {
const contractCode = e.data.contractCode
const sourceCode = {
language: 'Solidity',
sources: {
contract: {
content: contractCode,
}
},
settings: {
optimizer: {
enabled: true,
runs: 200,
},
outputSelection: {
'*': {
'*': ['abi'],
}
}
}
};
const m = createRevive();
m.soljson = Module;
// Set input data for stdin
m.writeToStdin(JSON.stringify(sourceCode));
// Compile the Solidity source code
m.callMain(['--standard-json']);
postMessage({output: m.readFromStdout() || m.readFromStderr()});
};
+5 -13
View File
@@ -1,23 +1,15 @@
{
"name": "revive",
"version": "1.0.0",
"description": "Revive compiler",
"main": "run_revive.js",
"type": "module",
"private": true,
"dependencies": {
"deasync": "^0.1.15",
"solc": "^0.8.28"
},
"scripts": {
"build": "cp ../target/wasm32-unknown-emscripten/release/resolc.js ../target/wasm32-unknown-emscripten/release/resolc.wasm ./src && npx rollup -c",
"test": "npm run build && node run_revive.js"
"fetch:soljson": "wget https://binaries.soliditylang.org/wasm/soljson-v0.8.28+commit.7893614a.js -O ./examples/web/soljson.js",
"example:web": "npm run fetch:soljson && http-server ./examples/web/",
"example:node": "node ./examples/node/run_revive.js"
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-node-resolve": "^15.3.0",
"rollup": "^4.27.3",
"rollup-plugin-copy": "^3.5.0"
"http-server": "^14.1.1"
}
}
-35
View File
@@ -1,35 +0,0 @@
import babel from '@rollup/plugin-babel';
import copy from 'rollup-plugin-copy';
import resolve from '@rollup/plugin-node-resolve';
const outputDirCJS = 'dist/revive-cjs';
const outputDirESM = 'dist/revive-esm';
export default {
input: ['src/resolc.js', 'src/worker.js'], // Adjust this to your main entry file
output: [
{
dir: outputDirCJS,
format: 'cjs',
exports: 'auto',
},
{
dir: outputDirESM,
format: 'esm',
},
],
plugins: [
babel({
exclude: 'node_modules/**',
presets: ['@babel/preset-env'],
babelHelpers: 'inline',
}),
resolve(),
copy({
targets: [
{ src: 'src/resolc.wasm', dest: outputDirCJS },
{ src: 'src/resolc.wasm', dest: outputDirESM },
],
})
],
};
-32
View File
@@ -1,32 +0,0 @@
import { parentPort } from 'worker_threads';
parentPort.on('message', async (inputJson) => {
const { default: createRevive } = await import(new URL('./resolc.js', import.meta.url));
const revive = await createRevive();
revive.setStdinData(inputJson);
let stdoutString = "";
revive.setStdoutCallback(function(char) {
if (char.charCodeAt(0) === '\n') {
console.log("new line")
exit
}
stdoutString += char;
});
let stderrString = "";
revive.setStderrCallback(function(char) {
stderrString += char;
});
// Call main on the new instance
const output = revive.callMain(['--recursive-process']);
if (stderrString.length > 0) {
// If /err is not empty, throw an error with its content
throw new Error(stderrString);
} else {
parentPort.postMessage({ output: stdoutString });
}
});
+1 -2
View File
@@ -3,8 +3,7 @@
"private": true,
"scripts": {
"test:cli": "npm run test -w crates/solidity/src/tests/cli-tests",
"build:revive": "npm run build -w js",
"test:revive": "npm run test -w js"
"test:revive": "npm run example:node -w js"
},
"workspaces": [
"crates/solidity/src/tests/cli-tests",