Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the fraud proof #124

Merged
merged 18 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions arbitrator/jit/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub fn create(opts: &Opts, env: WasmEnv) -> (Instance, FunctionEnv<WasmEnv>, Sto
},
"resolveTypedPreimage" => func!(wavmio::resolve_typed_preimage),
"readHotShotCommitment" => func!(wavmio::read_hotshot_commitment),
"getHotShotAvailability" => func!(wavmio::get_hotshot_availability),
"isHotShotLive" => func!(wavmio::is_hotshot_live),
},
"wasi_snapshot_preview1" => {
"proc_exit" => func!(wasip1_stub::proc_exit),
Expand Down Expand Up @@ -193,7 +193,7 @@ pub type Inbox = BTreeMap<u64, Vec<u8>>;
pub type Preimages = BTreeMap<PreimageType, BTreeMap<Bytes32, Vec<u8>>>;
pub type ModuleAsm = Arc<[u8]>;
pub type HotShotCommitmentMap = BTreeMap<u64, [u8; 32]>;
pub type HotShotAvailabilityMap = BTreeMap<u64, bool>;
pub type HotShotLivenessMap = BTreeMap<u64, bool>;

#[derive(Default)]
pub struct WasmEnv {
Expand All @@ -213,8 +213,8 @@ pub struct WasmEnv {
pub sequencer_messages: Inbox,
/// Mapping from batch positions to hotshot commitments
pub hotshot_comm_map: HotShotCommitmentMap,
/// Mapping from l1 height to hotshot availabilities
pub hotshot_avail_map: HotShotAvailabilityMap,
/// Mapping from l1 height to hotshot liveness
pub hotshot_avail_map: HotShotLivenessMap,
/// The delayed inbox's messages
pub delayed_messages: Inbox,
/// The purpose and connections of this process
Expand Down
23 changes: 13 additions & 10 deletions arbitrator/jit/src/wavmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,20 @@ pub fn read_inbox_message(
Ok(read.len() as u32)
}

pub fn get_hotshot_availability(mut env: WasmEnvMut, h: u64) -> Result<u32, Escape> {
pub fn is_hotshot_live(mut env: WasmEnvMut, h: u64) -> Result<u32, Escape> {
let (_mem, exec) = env.jit_env();
ready_hostio(exec)?;

let availability = match exec.hotshot_avail_map.get(&h) {
Some(availability) => availability,
let liveness = match exec.hotshot_avail_map.get(&h) {
Some(liveness) => liveness,
None => {
return Escape::hostio(format!(
"jit machine failed to read the hotshot availability at {}",
"jit machine failed to read the hotshot liveness at {}",
h
))
}
};
if *availability {
if *liveness {
Ok(1)
} else {
Ok(0)
Expand Down Expand Up @@ -301,18 +301,21 @@ fn ready_hostio(env: &mut WasmEnv) -> MaybeEscape {
let validated_hotshot_height = socket::read_u64(stream)?;
let hotshot_comm = socket::read_bytes32(stream)?;
let l1_block_height = socket::read_u64(stream)?;
let hotshot_avail = socket::read_u8(stream)?;
let hotshot_liveness = socket::read_u8(stream)?;

env.small_globals = [
inbox_position,
position_within_message,
validated_hotshot_height,
];
env.large_globals = [last_block_hash, last_send_root];
env.hotshot_comm_map
.insert(validated_hotshot_height + 1, hotshot_comm.0);
env.hotshot_avail_map
.insert(l1_block_height, hotshot_avail > 0);
if hotshot_liveness > 0 {
// HotShot is up
env.hotshot_comm_map.insert(l1_block_height, hotshot_comm.0);
} else {
env.hotshot_avail_map
.insert(l1_block_height, hotshot_liveness > 0);
}

while socket::read_u8(stream)? == socket::ANOTHER {
let position = socket::read_u64(stream)?;
Expand Down
10 changes: 5 additions & 5 deletions arbitrator/prover/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub enum Hostio {
WavmReadEthVersionedHashPreimage,
WavmReadInboxMessage,
WavmReadHotShotCommitment,
WavmGetHotShotAvailability,
WavmIsHotShotLive,
WavmReadDelayedInboxMessage,
WavmHaltAndSetFinished,
WavmLinkModule,
Expand Down Expand Up @@ -127,7 +127,7 @@ impl FromStr for Hostio {
("env", "wavm_read_inbox_message") => WavmReadInboxMessage,
("env", "wavm_read_delayed_inbox_message") => WavmReadDelayedInboxMessage,
("env", "wavm_read_hotshot_commitment") => WavmReadHotShotCommitment,
("env", "wavm_get_hotshot_availability") => WavmGetHotShotAvailability,
("env", "wavm_is_hotshot_live") => WavmIsHotShotLive,
("env", "wavm_halt_and_set_finished") => WavmHaltAndSetFinished,
("hostio", "wavm_link_module") => WavmLinkModule,
("hostio", "wavm_unlink_module") => WavmUnlinkModule,
Expand Down Expand Up @@ -191,7 +191,7 @@ impl Hostio {
WavmReadDelayedInboxMessage => func!([I64, I32, I32], [I32]),
WavmHaltAndSetFinished => func!(),
WavmReadHotShotCommitment => func!([I32, I64]),
WavmGetHotShotAvailability => func!([I64], [I32]),
WavmIsHotShotLive => func!([I64], [I32]),
WavmLinkModule => func!([I32], [I32]), // λ(module_hash) → module
WavmUnlinkModule => func!(), // λ()
ProgramInkLeft => func!([I32], [I64]), // λ(module) → ink_left
Expand Down Expand Up @@ -297,9 +297,9 @@ impl Hostio {
opcode!(LocalGet, 1);
opcode!(ReadHotShotCommitment);
}
WavmGetHotShotAvailability => {
WavmIsHotShotLive => {
opcode!(LocalGet, 0);
opcode!(GetHotShotAvailability);
opcode!(IsHotShotLive);
}
WavmReadEthVersionedHashPreimage => {
opcode!(LocalGet, 0);
Expand Down
11 changes: 11 additions & 0 deletions arbitrator/prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,17 @@ pub unsafe extern "C" fn arbitrator_add_hotshot_commitment(
}
}

#[no_mangle]
pub unsafe extern "C" fn arbitrator_add_hotshot_liveness(
mach: *mut Machine,
height: u64,
liveness: u8,
) -> c_int {
let mach = &mut *mach;
mach.add_hotshot_liveness(height, liveness > 0);
0
}

/// Adds a user program to the machine's known set of wasms.
#[no_mangle]
pub unsafe extern "C" fn arbitrator_add_user_wasm(
Expand Down
20 changes: 12 additions & 8 deletions arbitrator/prover/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ pub struct Machine {
stdio_output: Vec<u8>,
inbox_contents: HashMap<(InboxIdentifier, u64), Vec<u8>>,
hotshot_commitments: HashMap<u64, [u8; 32]>,
hotshot_availabilities: HashMap<u64, bool>,
hotshot_liveness: HashMap<u64, bool>,
first_too_far: u64, // Not part of machine hash
preimage_resolver: PreimageResolverWrapper,
/// Linkable Stylus modules in compressed form. Not part of the machine hash.
Expand Down Expand Up @@ -1550,7 +1550,7 @@ impl Machine {
context: 0,
hotshot_commitments: Default::default(),
debug_info,
hotshot_availabilities: Default::default(),
hotshot_liveness: Default::default(),
};
mach.initial_hash = mach.hash();
Ok(mach)
Expand Down Expand Up @@ -1602,7 +1602,7 @@ impl Machine {
initial_hash: Bytes32::default(),
context: 0,
hotshot_commitments: Default::default(),
hotshot_availabilities: Default::default(),
hotshot_liveness: Default::default(),
debug_info: false,
};
mach.initial_hash = mach.hash();
Expand Down Expand Up @@ -2492,9 +2492,9 @@ impl Machine {
error!()
}
}
Opcode::GetHotShotAvailability => {
Opcode::IsHotShotLive => {
let height = value_stack.pop().unwrap().assume_u64();
if let Some(is_alive) = self.hotshot_availabilities.get(&height) {
if let Some(is_alive) = self.hotshot_liveness.get(&height) {
let value = if *is_alive { 1 } else { 0 };
value_stack.push(Value::I32(value));
} else {
Expand Down Expand Up @@ -3102,13 +3102,13 @@ impl Machine {
panic!("Should never ever get here")
}
}
GetHotShotAvailability => {
IsHotShotLive => {
let h = value_stack.get(0).unwrap().assume_u64();
if let Some(avail) = self.hotshot_availabilities.get(&h) {
if let Some(avail) = self.hotshot_liveness.get(&h) {
let v: u8 = if *avail { 1 } else { 0 };
data.push(v);
} else {
panic!("cannot find the hotshot availability {}", h)
panic!("cannot find the hotshot liveness {}", h)
}
}
LinkModule | UnlinkModule => {
Expand Down Expand Up @@ -3216,6 +3216,10 @@ impl Machine {
self.hotshot_commitments.insert(height, commitment);
}

pub fn add_hotshot_liveness(&mut self, height: u64, liveness: bool) {
self.hotshot_liveness.insert(height, liveness);
}

pub fn get_module_names(&self, module: usize) -> Option<&NameCustomSection> {
self.modules.get(module).map(|m| &*m.names)
}
Expand Down
6 changes: 3 additions & 3 deletions arbitrator/prover/src/wavm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ pub enum Opcode {
/// Reads the HotShot commitment on the stack at an offset
ReadHotShotCommitment,
/// Gets the HotShot availability at a given L1 height
GetHotShotAvailability,
IsHotShotLive,
}

impl Opcode {
Expand Down Expand Up @@ -295,7 +295,7 @@ impl Opcode {
Opcode::SwitchThread => 0x8032,

Opcode::ReadHotShotCommitment => 0x9001,
Opcode::GetHotShotAvailability => 0x9002,
Opcode::IsHotShotLive => 0x9002,
}
}

Expand All @@ -309,7 +309,7 @@ impl Opcode {
| Opcode::ReadPreImage
| Opcode::ReadInboxMessage
| Opcode::ReadHotShotCommitment
| Opcode::GetHotShotAvailability
| Opcode::IsHotShotLive
)
}
}
Expand Down
6 changes: 3 additions & 3 deletions arbitrator/wasm-libraries/host-io/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extern "C" {
pub fn wavm_read_eth_versioned_hash_preimage(ptr: *mut u8, offset: usize) -> usize;
pub fn wavm_read_inbox_message(msg_num: u64, ptr: *mut u8, offset: usize) -> usize;
pub fn wavm_read_hotshot_commitment(ptr: *mut u8, height: u64);
pub fn wavm_get_hotshot_availability(height: u64) -> u32;
pub fn wavm_is_hotshot_live(height: u64) -> u32;
pub fn wavm_read_delayed_inbox_message(seq_num: u64, ptr: *mut u8, offset: usize) -> usize;
}

Expand Down Expand Up @@ -90,8 +90,8 @@ pub unsafe extern "C" fn wavmio__readHotShotCommitment(h: u64, out_ptr: GuestPtr
}

#[no_mangle]
pub unsafe extern "C" fn wavmio__getHotShotAvailability(h: u64) -> u32 {
wavm_get_hotshot_availability(h)
pub unsafe extern "C" fn wavmio__isHotShotLive(h: u64) -> u32 {
wavm_is_hotshot_live(h)
}

/// Reads an inbox message
Expand Down
30 changes: 0 additions & 30 deletions arbos/mock_light_client_reader.go

This file was deleted.

5 changes: 3 additions & 2 deletions cmd/replay/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ func main() {

hotshotHeader := jst.Header
height := hotshotHeader.Height
commitment := espressoTypes.Commitment(wavmio.ReadHotShotCommitment(height))
l1_height := jst.BlockMerkleJustification.L1ProofHeight
commitment := espressoTypes.Commitment(wavmio.ReadHotShotCommitment(l1_height))
validatedHeight := wavmio.GetEspressoHeight()
if validatedHeight == 0 {
// Validators can choose their own trusted starting point to start their validation.
Expand All @@ -314,7 +315,7 @@ func main() {
espressocrypto.VerifyMerkleProof(jst.BlockMerkleJustification.BlockMerkleProof.Proof, jsonHeader, *jst.BlockMerkleJustification.BlockMerkleComm, commitment)
} else if validatingEspressoLivenessFailure {
l1Block := message.Message.Header.BlockNumber
if wavmio.GetHotShotAvailability(l1Block) {
if wavmio.IsHotShotLive(l1Block) {
panic(fmt.Sprintf("getting the centralized message while hotshot is good, l1Height: %v", l1Block))
}
}
Expand Down
7 changes: 3 additions & 4 deletions execution/gethexec/switch_sequencer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/offchainlabs/nitro/arbos"
"github.com/offchainlabs/nitro/util/stopwaiter"
)

Expand Down Expand Up @@ -39,9 +38,9 @@ func NewSwitchSequencer(centralized *Sequencer, espresso *EspressoSequencer, l1c
return nil, err
}

var lightClient lightClient.LightClientReaderInterface
var lightclient lightClient.LightClientReaderInterface
if config.LightClientAddress != "" {
lightClient, err = arbos.NewMockLightClientReader(common.HexToAddress(config.LightClientAddress), l1client)
lightclient, err = lightClient.NewLightClientReader(common.HexToAddress(config.LightClientAddress), l1client)
if err != nil {
return nil, err
}
Expand All @@ -50,7 +49,7 @@ func NewSwitchSequencer(centralized *Sequencer, espresso *EspressoSequencer, l1c
return &SwitchSequencer{
centralized: centralized,
espresso: espresso,
lightClient: lightClient,
lightClient: lightclient,
mode: SequencingMode_Espresso,
maxHotShotDriftTime: config.MaxHotShotDriftTime,
switchPollInterval: config.SwitchPollInterval,
Expand Down
13 changes: 8 additions & 5 deletions staker/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,25 +585,28 @@ func (v *BlockValidator) createNextValidationEntry(ctx context.Context) (bool, e
return false, fmt.Errorf("illegal batch msg count %d pos %d batch %d", v.nextCreateBatchMsgCount, pos, endGS.Batch)
}
var comm espressoTypes.Commitment
var hotShotAvailability bool
var isHotShotLive bool
var l1BlockHeight uint64
if arbos.IsEspressoMsg(msg.Message) {
_, jst, err := arbos.ParseEspressoMsg(msg.Message)
if err != nil {
return false, err
}
fetchedCommitment, err := v.lightClientReader.FetchMerkleRootAtL1Block(jst.BlockMerkleJustification.L1ProofHeight)
l1BlockHeight = jst.BlockMerkleJustification.L1ProofHeight
fetchedCommitment, err := v.lightClientReader.FetchMerkleRootAtL1Block(l1BlockHeight)
if err != nil {
log.Error("error attempting to fetch block merkle root from the light client contract", "L1ProofHeight", jst.BlockMerkleJustification.L1ProofHeight)
return false, err
}
comm = fetchedCommitment
hotShotAvailability = true
isHotShotLive = true
} else if arbos.IsL2NonEspressoMsg(msg.Message) {
hotShotAvailability = false
isHotShotLive = false
l1BlockHeight = msg.Message.Header.BlockNumber
}
chainConfig := v.streamer.ChainConfig()
entry, err := newValidationEntry(
pos, v.nextCreateStartGS, endGS, msg, v.nextCreateBatch, v.nextCreateBatchBlockHash, v.nextCreatePrevDelayed, chainConfig, &comm, hotShotAvailability,
pos, v.nextCreateStartGS, endGS, msg, v.nextCreateBatch, v.nextCreateBatchBlockHash, v.nextCreatePrevDelayed, chainConfig, &comm, isHotShotLive, l1BlockHeight,
)
if err != nil {
return false, err
Expand Down
Loading
Loading