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

Commit

Permalink
Merge branch 'stylus' into rename-memory-grow
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuacolvin0 authored Dec 7, 2023
2 parents 98345d9 + 0238d72 commit 768c397
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 64 deletions.
10 changes: 5 additions & 5 deletions arbitrator/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion arbitrator/wasm-libraries/user-host/src/host.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE

use crate::{evm_api::ApiCaller, Program};
use crate::{evm_api::ApiCaller, program::Program};
use arbutil::{
crypto,
evm::{self, api::EvmApi, js::JsEvmApi, user::UserOutcomeKind},
Expand Down
2 changes: 1 addition & 1 deletion arbitrator/wasm-libraries/user-host/src/ink.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2022-2023, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE

use crate::Program;
use crate::program::Program;
use prover::programs::{
config::PricingParams,
prelude::{GasMeteredMachine, MachineMeter, MeteredMachine},
Expand Down
49 changes: 1 addition & 48 deletions arbitrator/wasm-libraries/user-host/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,55 +1,8 @@
// Copyright 2022-2023, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE

use arbutil::{
evm::{js::JsEvmApi, EvmData},
pricing,
};
use evm_api::ApiCaller;
use prover::programs::{meter::MeteredMachine, prelude::StylusConfig};

mod evm_api;
mod host;
mod ink;
mod link;

pub(crate) static mut PROGRAMS: Vec<Program> = vec![];

pub(crate) struct Program {
args: Vec<u8>,
outs: Vec<u8>,
evm_api: JsEvmApi<ApiCaller>,
evm_data: EvmData,
config: StylusConfig,
}

impl Program {
pub fn new(
args: Vec<u8>,
evm_api: JsEvmApi<ApiCaller>,
evm_data: EvmData,
config: StylusConfig,
) -> Self {
Self {
args,
outs: vec![],
evm_api,
evm_data,
config,
}
}

pub fn into_outs(self) -> Vec<u8> {
self.outs
}

pub fn start(cost: u64) -> &'static mut Self {
let program = Self::start_free();
program.buy_ink(pricing::HOSTIO_INK + cost).unwrap();
program
}

pub fn start_free() -> &'static mut Self {
unsafe { PROGRAMS.last_mut().expect("no program") }
}
}
mod program;
6 changes: 3 additions & 3 deletions arbitrator/wasm-libraries/user-host/src/link.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2022-2023, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE

use crate::{evm_api::ApiCaller, Program, PROGRAMS};
use crate::{evm_api::ApiCaller, program::Program};
use arbutil::{
evm::{js::JsEvmApi, user::UserOutcomeKind, EvmData},
format::DebugBytes,
Expand Down Expand Up @@ -119,11 +119,11 @@ pub unsafe extern "C" fn go__github_com_offchainlabs_nitro_arbos_programs_callPr

// provide arguments
let args_len = calldata.len();
PROGRAMS.push(Program::new(calldata, evm_api, evm_data, config));
Program::push_new(calldata, evm_api, evm_data, config);

// call the program
let status = program_call_main(module, args_len);
let outs = PROGRAMS.pop().unwrap().into_outs();
let outs = Program::pop();
sp.restore_stack(); // restore the stack pointer (corrupts during EVM API calls)

/// cleans up and writes the output
Expand Down
70 changes: 70 additions & 0 deletions arbitrator/wasm-libraries/user-host/src/program.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2022-2023, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE

use crate::evm_api::ApiCaller;
use arbutil::{
evm::{js::JsEvmApi, EvmData},
pricing,
};
use prover::programs::{meter::MeteredMachine, prelude::StylusConfig};

/// The list of active programs. The current program is always the last.
///
/// Note that this data-structure may re-alloc while references to [`Program`] are held.
/// This is sound due to [`Box`] providing a level of indirection.
///
/// Normal Rust rules would suggest using a [`Vec`] of cells would be better. The issue is that,
/// should an error guard recover, this WASM will reset to an earlier state but with the current
/// memory. This means that stack unwinding won't happen, rendering these primitives unhelpful.
#[allow(clippy::vec_box)]
static mut PROGRAMS: Vec<Box<Program>> = vec![];

/// An active user program.
pub(crate) struct Program {
/// Arguments passed via the VM.
pub args: Vec<u8>,
/// Output generated by the program.
pub outs: Vec<u8>,
/// Mechanism for calling back into Geth.
pub evm_api: JsEvmApi<ApiCaller>,
/// EVM Context info.
pub evm_data: EvmData,
/// Call configuration.
pub config: StylusConfig,
}

impl Program {
/// Adds a new program, making it current.
pub fn push_new(
args: Vec<u8>,
evm_api: JsEvmApi<ApiCaller>,
evm_data: EvmData,
config: StylusConfig,
) {
let program = Self {
args,
outs: vec![],
evm_api,
evm_data,
config,
};
unsafe { PROGRAMS.push(Box::new(program)) }
}

/// Removes the current program, returning its output.
pub fn pop() -> Vec<u8> {
unsafe { PROGRAMS.pop().expect("no program").outs }
}

/// Provides a reference to the current program after paying some ink.
pub fn start(cost: u64) -> &'static mut Self {
let program = Self::start_free();
program.buy_ink(pricing::HOSTIO_INK + cost).unwrap();
program
}

/// Provides a reference to the current program.
pub fn start_free() -> &'static mut Self {
unsafe { PROGRAMS.last_mut().expect("no program") }
}
}
18 changes: 14 additions & 4 deletions arbnode/delayed.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type
}

messages := make([]*DelayedInboxMessage, 0, len(logs))
var lastParentChainBlockNumber uint64
var lastL1BlockNumber uint64
for _, parsedLog := range parsedLogs {
msgKey := common.BigToHash(parsedLog.MessageIndex)
data, ok := messageData[msgKey]
Expand All @@ -196,9 +198,17 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type

requestId := common.BigToHash(parsedLog.MessageIndex)
parentChainBlockNumber := parsedLog.Raw.BlockNumber
l1BlockNumber, err := arbutil.CorrespondingL1BlockNumber(ctx, b.client, parentChainBlockNumber)
if err != nil {
return nil, err
var l1BlockNumber uint64
if lastParentChainBlockNumber == parentChainBlockNumber && lastParentChainBlockNumber > 0 {
l1BlockNumber = lastL1BlockNumber
} else {
var err error
l1BlockNumber, err = arbutil.CorrespondingL1BlockNumber(ctx, b.client, parentChainBlockNumber)
if err != nil {
return nil, err
}
lastParentChainBlockNumber = parentChainBlockNumber
lastL1BlockNumber = l1BlockNumber
}
msg := &DelayedInboxMessage{
BlockHash: parsedLog.Raw.BlockHash,
Expand All @@ -216,7 +226,7 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type
},
ParentChainBlockNumber: parsedLog.Raw.BlockNumber,
}
err = msg.Message.FillInBatchGasCost(batchFetcher)
err := msg.Message.FillInBatchGasCost(batchFetcher)
if err != nil {
return nil, err
}
Expand Down
3 changes: 2 additions & 1 deletion arbos/programs/native.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,11 @@ func callProgram(
(*u64)(&scope.Contract.Gas),
))

depth := interpreter.Depth()
debug := stylusParams.debugMode != 0
data, msg, err := status.toResult(output.intoBytes(), debug)
if status == userFailure && debug {
log.Warn("program failure", "err", err, "msg", msg, "program", address)
log.Warn("program failure", "err", err, "msg", msg, "program", address, "depth", depth)
}
return data, err
}
Expand Down
12 changes: 11 additions & 1 deletion system_tests/program_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ func errorTest(t *testing.T, jit bool) {
defer cleanup()

programAddress := deployWasm(t, ctx, auth, l2client, rustFile("fallible"))
multiAddr := deployWasm(t, ctx, auth, l2client, rustFile("multicall"))

// ensure tx passes
tx := l2info.PrepareTxTo("Owner", &programAddress, l2info.TransferGas, nil, []byte{0x01})
Expand All @@ -246,7 +247,16 @@ func errorTest(t *testing.T, jit bool) {
Fatal(t, "call should have failed")
}

validateBlocks(t, 6, jit, ctx, node, l2client)
// ensure tx recovery is correct after failing in a deeply nested call
args := []byte{}
for i := 0; i < 32; i++ {
args = argsForMulticall(vm.CALL, multiAddr, nil, args)
}
tx = l2info.PrepareTxTo("Owner", &multiAddr, 1e9, nil, args)
Require(t, l2client.SendTransaction(ctx, tx))
EnsureTxFailed(t, ctx, l2client, tx)

validateBlocks(t, 7, jit, ctx, node, l2client)
}

func TestProgramStorage(t *testing.T) {
Expand Down

0 comments on commit 768c397

Please sign in to comment.