Skip to content
This repository was archived by the owner on Nov 26, 2024. It is now read-only.

Commit 3b3a1a4

Browse files
Merge pull request #236 from OffchainLabs/stylus-nitro-conflicts
Resolve Stylus Nitro Conflicts
2 parents 46c29f5 + 328b83c commit 3b3a1a4

File tree

100 files changed

+2540
-756
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+2540
-756
lines changed

Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,5 +316,15 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
316316

317317
USER user
318318

319+
FROM nitro-node-dev as nitro-node-split
320+
USER root
321+
322+
RUN export DEBIAN_FRONTEND=noninteractive && \
323+
apt-get update && \
324+
apt-get install -y xxd netcat-traditional
325+
COPY scripts/split-val-entry.sh /usr/local/bin
326+
ENTRYPOINT [ "/usr/local/bin/split-val-entry.sh" ]
327+
USER user
328+
319329
FROM nitro-node as nitro-node-default
320330
# Just to ensure nitro-node-dist is default

README.md

Lines changed: 29 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,58 @@
11
<br />
22
<p align="center">
33
<a href="https://arbitrum.io/">
4-
<img src="https://arbitrum.io/assets/stylus/stylus_with_paint_bg.png" alt="Logo" width="100%">
4+
<img src="https://arbitrum.io/assets/arbitrum/logo_color.png" alt="Logo" width="80" height="80">
55
</a>
66

7+
<h3 align="center">Arbitrum Nitro</h3>
8+
79
<p align="center">
810
<a href="https://developer.arbitrum.io/"><strong>Next Generation Ethereum L2 Technology »</strong></a>
911
<br />
1012
</p>
1113
</p>
1214

13-
## About Arbitrum Stylus
14-
15-
Stylus is a next-gen programming environment for Arbitrum chains. Through the power of WebAssembly smart contracts, users can deploy programs written in their favorite programming languages, including Rust, C, and C++, to run alongside EVM smart contracts on Arbitrum. It's over an order of magnitude faster, slashes fees, and is fully interoperable with the Ethereum Virtual Machine.
16-
17-
This repo is a fork of [Arbitrum Nitro][Nitro] and is designed as an upgrade for all Arbitrum chains. Included is the Stylus VM and working fraud prover. If you are looking to write and deploy Stylus programs, please see the following SDKs.
18-
19-
| Repo | Use cases | License |
20-
|:-------------------------------|:----------------------------|:------------------|
21-
| [Rust SDK][Rust] | Everything! | Apache 2.0 or MIT |
22-
| [C/C++ SDK][C] | Cryptography and algorithms | Apache 2.0 or MIT |
23-
| [Bf SDK][Bf] | Educational | Apache 2.0 or MIT |
24-
| [Cargo Stylus CLI Tool][Cargo] | Program deployment | Apache 2.0 or MIT |
25-
26-
[Nitro]: https://github.com/OffchainLabs/nitro
27-
[Orbit]: https://docs.arbitrum.io/launch-orbit-chain/orbit-gentle-introduction
28-
29-
Stylus is entirely opt-in. Devs familiar with Solidity can continue to enjoy Arbitrum's EVM-equivalent experience without any changes. This is because Stylus is entirely additive &mdash; a model we call EVM+. Stylus introduces a second, fully composible virtual machine for executing WebAssembly that coordinates with the EVM to produce state transitions. And since the Stylus SDK uses solidity ABIs, a contract written in one language can call out to any other.
30-
31-
For example, existing Solidity DEXs can &mdash; without modifications &mdash; list Rust ERC20 tokens, which might call out to C programs to do cryptography. Everything is fully interoperable, so users never have to care about the specific language or implementation details of the contracts they call.
32-
33-
## Roadmap
15+
## About Arbitrum Nitro
3416

35-
Stylus is currently testnet-only and not recommended for production use. This will change as we complete an audit and add additional features.
17+
<img src="https://arbitrum.io/assets/arbitrum/logo_color.png" alt="Logo" width="80" height="80">
3618

37-
Arbitrum [Orbit L3s][Orbit] may opt into Stylus at any time. Arbitrum One and Arbitrum Nova will upgrade to Stylus should the DAO vote for it.
19+
Nitro is the latest iteration of the Arbitrum technology. It is a fully integrated, complete
20+
layer 2 optimistic rollup system, including fraud proofs, the sequencer, the token bridges,
21+
advanced calldata compression, and more.
3822

39-
If you'd like to be a part of this journey, join us in the `#stylus` channel on [Discord][discord]!
23+
See the live docs-site [here](https://developer.arbitrum.io/) (or [here](https://github.com/OffchainLabs/arbitrum-docs) for markdown docs source.)
4024

41-
## Gas Pricing
25+
See [here](./audits) for security audit reports.
4226

43-
Stylus introduces new pricing models for WASM programs. Intended for high-compute applications, Stylus makes the following more affordable:
27+
The Nitro stack is built on several innovations. At its core is a new prover, which can do Arbitrum’s classic
28+
interactive fraud proofs over WASM code. That means the L2 Arbitrum engine can be written and compiled using
29+
standard languages and tools, replacing the custom-designed language and compiler used in previous Arbitrum
30+
versions. In normal execution,
31+
validators and nodes run the Nitro engine compiled to native code, switching to WASM if a fraud proof is needed.
32+
We compile the core of Geth, the EVM engine that practically defines the Ethereum standard, right into Arbitrum.
33+
So the previous custom-built EVM emulator is replaced by Geth, the most popular and well-supported Ethereum client.
4434

45-
- Compute, which is generally **10-100x** cheaper depending on the program. This is primarily due to the efficiency of the WASM runtime relative to the EVM, and the quality of the code produced by Rust, C, and C++ compilers. Another factor that matters is the quality of the code itself. For example, highly optimized and audited C libraries that implement a particular cryptographic operation are usually deployable without modification and perform exceptionally well. The fee reduction may be smaller for highly optimized Solidity that makes heavy use of native precompiles vs an unoptimized Stylus equivalent that doesn't do the same.
35+
The last piece of the stack is a slimmed-down version of our ArbOS component, rewritten in Go, which provides the
36+
rest of what’s needed to run an L2 chain: things like cross-chain communication, and a new and improved batching
37+
and compression system to minimize L1 costs.
4638

47-
- Memory, which is **100-500x** cheaper due to Stylus's novel exponential pricing mechanism intended to address Vitalik's concerns with the EVM's per-call, [quadratic memory][quadratic] pricing policy. For the first time ever, high-memory applications are possible on an EVM-equivalent chain.
39+
Essentially, Nitro runs Geth at layer 2 on top of Ethereum, and can prove fraud over the core engine of Geth
40+
compiled to WASM.
4841

49-
- Storage, for which the Rust SDK promotes better access patterns and type choices. Note that while the underlying [`SLOAD`][SLOAD] and [`SSTORE`][SSTORE] operations cost as they do in the EVM, the Rust SDK implements an optimal caching policy that minimizes their use. Exact savings depends on the program.
50-
51-
- VM affordances, including common operations like keccak and reentrancy detection. No longer is it expensive to make safety the default.
52-
53-
There are, however, minor overheads to using Stylus that may matter to your application:
54-
55-
- The first time a WASM is deployed, it must be _activated_. This is generally a few million gas, though to avoid testnet DoS, we've set it to a fixed 14 million. Note that you do not have to activate future copies of the same program. For example, the same NFT template can be deployed many times without paying this cost more than once. We will soon make the fees paid depend on the program, so that the gas used is based on the complexity of the WASM instead of this very conservative, worst-case estimate.
56-
57-
- Calling a Stylus program costs 200-2000 gas. We're working with Wasmer to improve setup costs, but there will likely always be some amount of gas one pays to jump into WASM execution. This means that if a contract does next to nothing, it may be cheaper in Solidity. However if a contract starts doing interesting work, the dynamic fees will quickly make up for this fixed-cost overhead.
58-
59-
Though conservative bounds have been chosen for testnet, all of this is subject to change as pricing models mature and further optimizations are made. Since gas numbers will vary across updates, it may make more sense to clock the time it takes to perform an operation rather than going solely by the numbers reported in receipts.
60-
61-
[quadratic]: https://notes.ethereum.org/@vbuterin/proposals_to_adjust_memory_gas_costs
62-
[SLOAD]: https://www.evm.codes/#54
63-
[SSTORE]: https://www.evm.codes/#55
42+
Arbitrum One successfully migrated from the Classic Arbitrum stack onto Nitro on 8/31/22. (See [state migration](https://developer.arbitrum.io/migration/state-migration) and [dapp migration](https://developer.arbitrum.io/migration/dapp_migration) for more info).
6443

6544
## License
6645

67-
We currently have the Stylus VM and fraud prover (the contents of this repo) [licensed](./LICENSE) under a Business Source License, similar to our friends at Uniswap and Aave, with an "Additional Use Grant" to ensure that everyone can have full comfort using and running nodes on all public Arbitrum chains.
46+
Nitro is currently licensed under a [Business Source License](./LICENSE.md), similar to our friends at Uniswap and Aave, with an "Additional Use Grant" to ensure that everyone can have full comfort using and running nodes on all public Arbitrum chains.
6847

69-
The Stylus SDK, however, is licensed under different terms. Please see each repo below for more information.
48+
The Additional Use Grant also permits the deployment of the Nitro software, in a permissionless fashion and without cost, as a new blockchain provided that the chain settles to either Arbitrum One or Arbitrum Nova.
7049

71-
| Repo | Use cases | License |
72-
|:-------------------------------|:----------------------------|:------------------|
73-
| [Rust SDK][Rust] | Everything! | Apache 2.0 or MIT |
74-
| [C/C++ SDK][C] | Cryptography and algorithms | Apache 2.0 or MIT |
75-
| [Bf SDK][Bf] | Educational | Apache 2.0 or MIT |
76-
| [Cargo Stylus CLI Tool][Cargo] | Program deployment | Apache 2.0 or MIT |
77-
78-
[Rust]: https://github.com/OffchainLabs/stylus-sdk-rs
79-
[C]: https://github.com/OffchainLabs/stylus-sdk-c
80-
[Bf]: https://github.com/OffchainLabs/stylus-sdk-bf
81-
[Cargo]: https://github.com/OffchainLabs/cargo-stylus
50+
For those that prefer to deploy the Nitro software either directly on Ethereum (i.e. an L2) or have it settle to another Layer-2 on top of Ethereum, the [Arbitrum Expansion Program (the "AEP")](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024-4f08b0c2cb476a55dc153380fa3e64b0.pdf) was recently established. The AEP allows for the permissionless deployment in the aforementioned fashion provided that 10% of net revenue (as more fully described in the AEP) is contributed back to the Arbitrum community in accordance with the requirements of the AEP.
8251

8352
## Contact
8453

85-
Discord - [Arbitrum][discord]
54+
Discord - [Arbitrum](https://discord.com/invite/5KE54JwyTs)
55+
56+
Twitter: [Arbitrum](https://twitter.com/arbitrum)
8657

87-
Twitter - [OffchainLabs](https://twitter.com/OffchainLabs)
8858

89-
[discord]: https://discord.com/invite/5KE54JwyTs

arbitrator/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

arbitrator/caller-env/src/guest_ptr.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,9 @@ impl Deref for GuestPtr {
4141
&self.0
4242
}
4343
}
44+
45+
impl GuestPtr {
46+
pub fn to_u64(self) -> u64 {
47+
self.into()
48+
}
49+
}

arbitrator/prover/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ num-traits = "0.2.17"
3939
c-kzg = { version = "0.4.0", optional = true } # TODO: look into switching to rust-kzg (no crates.io release or hosted rustdoc yet)
4040
sha2 = "0.9.9"
4141
lru = "0.12.3"
42+
once_cell = "1.19.0"
4243

4344
[lib]
4445
name = "prover"

arbitrator/prover/src/lib.rs

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use machine::{
3030
argument_data_to_inbox, get_empty_preimage_resolver, GlobalState, MachineStatus,
3131
PreimageResolver,
3232
};
33+
use once_cell::sync::OnceCell;
3334
use static_assertions::const_assert_eq;
3435
use std::{
3536
ffi::CStr,
@@ -45,7 +46,7 @@ use std::{
4546
use utils::CBytes;
4647

4748
lazy_static::lazy_static! {
48-
static ref BLOBHASH_PREIMAGE_CACHE: Mutex<LruCache<Bytes32, CBytes>> = Mutex::new(LruCache::new(NonZeroUsize::new(12).unwrap()));
49+
static ref BLOBHASH_PREIMAGE_CACHE: Mutex<LruCache<Bytes32, Arc<OnceCell<CBytes>>>> = Mutex::new(LruCache::new(NonZeroUsize::new(12).unwrap()));
4950
}
5051

5152
#[repr(C)]
@@ -332,28 +333,32 @@ pub struct ResolvedPreimage {
332333
pub len: isize, // negative if not found
333334
}
334335

335-
macro_rules! handle_preimage_resolution {
336-
($context:expr, $ty:expr, $hash:expr, $resolver:expr) => {{
337-
let res = $resolver($context, $ty.into(), $hash.as_ptr());
338-
if res.len < 0 {
339-
return None;
340-
}
341-
let data = CBytes::from_raw_parts(res.ptr, res.len as usize);
342-
// Check if preimage rehashes to the provided hash
343-
match crate::utils::hash_preimage(&data, $ty) {
344-
Ok(have_hash) if have_hash.as_slice() == *$hash => {}
345-
Ok(got_hash) => panic!(
346-
"Resolved incorrect data for hash {} (rehashed to {})",
347-
$hash,
348-
Bytes32(got_hash),
349-
),
350-
Err(err) => panic!(
351-
"Failed to hash preimage from resolver (expecting hash {}): {}",
352-
$hash, err,
353-
),
354-
}
355-
Some(data)
356-
}};
336+
#[cfg(feature = "native")]
337+
unsafe fn handle_preimage_resolution(
338+
context: u64,
339+
ty: PreimageType,
340+
hash: Bytes32,
341+
resolver: unsafe extern "C" fn(u64, u8, *const u8) -> ResolvedPreimage,
342+
) -> Option<CBytes> {
343+
let res = resolver(context, ty.into(), hash.as_ptr());
344+
if res.len < 0 {
345+
return None;
346+
}
347+
let data = CBytes::from_raw_parts(res.ptr, res.len as usize);
348+
// Check if preimage rehashes to the provided hash
349+
match crate::utils::hash_preimage(&data, ty) {
350+
Ok(have_hash) if have_hash.as_slice() == *hash => {}
351+
Ok(got_hash) => panic!(
352+
"Resolved incorrect data for hash {} (rehashed to {})",
353+
hash,
354+
Bytes32(got_hash),
355+
),
356+
Err(err) => panic!(
357+
"Failed to hash preimage from resolver (expecting hash {}): {}",
358+
hash, err,
359+
),
360+
}
361+
Some(data)
357362
}
358363

359364
#[no_mangle]
@@ -364,18 +369,19 @@ pub unsafe extern "C" fn arbitrator_set_preimage_resolver(
364369
) {
365370
(*mach).set_preimage_resolver(Arc::new(
366371
move |context: u64, ty: PreimageType, hash: Bytes32| -> Option<CBytes> {
367-
if let PreimageType::EthVersionedHash = ty {
368-
let mut cache = BLOBHASH_PREIMAGE_CACHE.lock().unwrap();
369-
if cache.contains(&hash) {
370-
return cache.get(&hash).cloned();
371-
}
372-
if let Some(data) = handle_preimage_resolution!(context, ty, hash, resolver) {
373-
cache.put(hash, data.clone());
374-
return Some(data);
375-
}
376-
return None;
372+
if ty == PreimageType::EthVersionedHash {
373+
let cache: Arc<OnceCell<CBytes>> = {
374+
let mut locked = BLOBHASH_PREIMAGE_CACHE.lock().unwrap();
375+
locked.get_or_insert(hash, Default::default).clone()
376+
};
377+
return cache
378+
.get_or_try_init(|| {
379+
handle_preimage_resolution(context, ty, hash, resolver).ok_or(())
380+
})
381+
.ok()
382+
.cloned();
377383
}
378-
handle_preimage_resolution!(context, ty, hash, resolver)
384+
handle_preimage_resolution(context, ty, hash, resolver)
379385
},
380386
) as PreimageResolver);
381387
}

arbitrator/prover/src/programs/meter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ pub fn pricing_v1(op: &Operator, tys: &HashMap<SignatureIndex, FunctionType>) ->
401401
dot!(I32Store, I32Store8, I32Store16) => 825,
402402
dot!(I64Store, I64Store8, I64Store16, I64Store32) => 950,
403403
dot!(MemorySize) => 3000,
404-
dot!(MemoryGrow) => 1, // cost handled by memory pricer
404+
dot!(MemoryGrow) => 8050, // rest of cost handled by memory pricer
405405

406406
op!(I32Eqz, I32Eq, I32Ne, I32LtS, I32LtU, I32GtS, I32GtU, I32LeS, I32LeU, I32GeS, I32GeU) => 170,
407407
op!(I64Eqz, I64Eq, I64Ne, I64LtS, I64LtU, I64GtS, I64GtU, I64LeS, I64LeU, I64GeS, I64GeU) => 225,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
;; Copyright 2023-2024, Offchain Labs, Inc.
2+
;; For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE
3+
4+
(module
5+
(import "console" "tee_i32" (func $tee_i32 (param i32) (result i32)))
6+
(func (export "user_entrypoint") (param $args_len i32) (result i32)
7+
;; fail to grow the memory a non-zero number of pages
8+
i32.const -65537
9+
call $tee_i32
10+
memory.grow
11+
call $tee_i32
12+
i32.const -1
13+
i32.eq
14+
i32.eqz
15+
(if (then unreachable))
16+
17+
;; succeed growing 0 pages
18+
i32.const 0
19+
memory.grow
20+
call $tee_i32
21+
i32.eqz
22+
i32.eqz
23+
)
24+
(memory (export "memory") 0 0)
25+
)

0 commit comments

Comments
 (0)