Skip to content

Commit

Permalink
Merge pull request risc0#52 from taikoxyz/sp1-stuff
Browse files Browse the repository at this point in the history
Sp1 stuff + re-enable risc0 + invalid tx support
  • Loading branch information
Brechtpd authored Mar 9, 2024
2 parents f4cf3a2 + b627f2a commit ebcfdd4
Show file tree
Hide file tree
Showing 14 changed files with 1,215 additions and 193 deletions.
1,028 changes: 980 additions & 48 deletions Cargo.lock

Large diffs are not rendered by default.

43 changes: 40 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,51 @@ $ cargo build

Run the host in a terminal that will listen to requests:

Just for development with the native prover:
```
RISC0_DEV_MODE=1 cargo run
cargo run
```

Then in another terminal you can do requests like this:

```
./prove_block.sh testnet risc0 10
./prove_block.sh testnet native 10
```

Look into `prove_block.sh` for the available options or run the script without inputs and it will tell you.
Look into `prove_block.sh` for the available options or run the script without inputs and it will tell you.

## Provers

Provers can be enabled using features. To compile with all of them (using standard options):

```
cargo run --release --features "risc0 succinct"
```

### risc zero
#### Testing
```
RISC0_DEV_MODE=1 cargo run --release --features risc0
```

#### CPU
```
cargo run --release --features risc0
```

#### GPU

```
RISC0_DEV_MODE=1 cargo run -F cuda --release --features risc0
```
OR
```
RISC0_DEV_MODE=1 cargo run -F metal --release --features risc0
```

CUDA needs to be installed when using `cuda`: https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html

### succinct's SP1:
```
cargo run --release --features succinct
```
86 changes: 58 additions & 28 deletions lib/src/builder/execute/taiko.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ use anyhow::{anyhow, bail, Context, Result};
use log::debug;
use revm::{
interpreter::Host,
primitives::{Account, Address, ResultAndState, SpecId, TransactTo, TxEnv},
primitives::{
Account, Address, EVMError, InvalidTransaction, ResultAndState, SpecId, TransactTo, TxEnv,
},
taiko, Database, DatabaseCommit, Evm,
};
use ruint::aliases::U256;
Expand All @@ -38,7 +40,7 @@ use crate::{
builder::BlockBuilder,
consts::{self, ChainSpec, GWEI_TO_WEI},
guest_mem_forget,
taiko_utils::{check_anchor_tx, get_contracts},
taiko_utils::{check_anchor_tx, generate_transactions, generate_transactions_2, get_contracts},
};

/// Minimum supported protocol version: Bedrock (Block no. 105235063).
Expand All @@ -65,25 +67,24 @@ impl TxExecStrategy<EthereumTxEssence> for TkoTxExecStrategy {
}
let chain_id = block_builder.chain_spec.chain_id();

// generate the transactions from the tx list
let mut transactions = generate_transactions_2(
&block_builder.input.taiko.tx_list,
block_builder.input.taiko.anchor_tx.clone().unwrap(),
);

#[cfg(feature = "std")]
{
use chrono::{TimeZone, Utc};
use log::info;
let dt = Utc
.timestamp_opt(
block_builder
.input
.timestamp
.try_into()
.expect("Timestamp could not fit into i64"),
0,
)
.timestamp_opt(block_builder.input.timestamp.try_into().unwrap(), 0)
.unwrap();

info!("Block no. {}", header.number);
info!(" EVM spec ID: {spec_id:?}");
info!(" Timestamp: {dt}");
info!(" Transactions: {}", block_builder.input.transactions.len());
info!(" Transactions: {}", transactions.len());
info!(" Fee Recipient: {:?}", block_builder.input.beneficiary);
info!(" Gas limit: {}", block_builder.input.gas_limit);
info!(" Base fee per gas: {}", header.base_fee_per_gas);
Expand Down Expand Up @@ -119,21 +120,30 @@ impl TxExecStrategy<EthereumTxEssence> for TkoTxExecStrategy {
// process all the transactions
let mut tx_trie = MptNode::default();
let mut receipt_trie = MptNode::default();
#[allow(unused_variables)]
// track the actual tx number to use in the tx/receipt trees as the key
let mut actual_tx_no = 0usize;

for (tx_no, tx) in take(&mut block_builder.input.transactions)
.into_iter()
.enumerate()
{
for (tx_no, tx) in take(&mut transactions).into_iter().enumerate() {
// anchor transaction must be executed successfully
let is_anchor = tx_no == 0;

// verify the transaction signature
let tx_from = tx
.recover_from()
.with_context(|| anyhow!("Error recovering address for transaction {tx_no}"))?;
let tx_from = match tx.recover_from() {
Ok(tx_from) => tx_from,
Err(err) => {
if is_anchor {
bail!("Error recovering anchor signature: {}", err);
}
#[cfg(not(target_os = "zkvm"))]
debug!(
"Error recovering address for transaction {}, error: {}",
tx_no, err
);
// If the signature is not valid, skip the transaction
continue;
}
};

// verify the anchor tx
if is_anchor {
check_anchor_tx(
&block_builder.input,
Expand All @@ -159,19 +169,39 @@ impl TxExecStrategy<EthereumTxEssence> for TkoTxExecStrategy {
bail!("Error at transaction {tx_no}: gas exceeds block limit");
}

// setup the transaction
fill_eth_tx_env(
&block_builder.input.taiko.chain_spec_name,
&mut evm.env().tx,
&tx.essence,
tx_from,
is_anchor,
);

// process the transaction
let ResultAndState { result, state } = evm
.transact()
.map_err(|evm_err| anyhow!("Error at transaction {tx_no}: {evm_err:?}"))?;
let ResultAndState { result, state } = match evm.transact() {
Ok(result) => result,
Err(err) => {
if is_anchor {
bail!("Error at transaction {}: {:?}", tx_no, err);
}
// only continue for invalid tx errors, not db errors (because those can be
// manipulated by the prover)
match err {
EVMError::Transaction(invalid_transaction) => {
#[cfg(not(target_os = "zkvm"))]
debug!("Invalid tx at {}: {:?}", tx_no, invalid_transaction);
// skip the tx
continue;
}
_ => {
// any other error is not allowed
bail!("Invalid tx at {}: {:?}", tx_no, err);
}
}
}
};

// anchor tx needs to succeed
if is_anchor && !result.is_success() {
bail!(
"Error at transaction {tx_no}: execute anchor failed {result:?}, output {:?}",
Expand Down Expand Up @@ -221,17 +251,17 @@ impl TxExecStrategy<EthereumTxEssence> for TkoTxExecStrategy {
}
}

actual_tx_no += 1;

// update the state
evm.context.evm.db.commit(state);

// accumulate logs to the block bloom filter
logs_bloom.accrue_bloom(&receipt.payload.logs_bloom);

// Add receipt and tx to tries
let trie_key = tx_no.to_rlp();
let trie_key = actual_tx_no.to_rlp();
tx_trie.insert_rlp(&trie_key, tx)?;
receipt_trie.insert_rlp(&trie_key, receipt)?;
actual_tx_no += 1;
}

let mut db = &mut evm.context.evm.db;
Expand Down Expand Up @@ -273,7 +303,7 @@ impl TxExecStrategy<EthereumTxEssence> for TkoTxExecStrategy {
};

// Leak memory, save cycles
guest_mem_forget([tx_trie, receipt_trie]);
guest_mem_forget([tx_trie, receipt_trie, withdrawals_trie]);
// Return block builder with updated database
Ok(block_builder.with_db(evm.context.evm.db))
}
Expand Down
47 changes: 24 additions & 23 deletions lib/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,30 @@ pub struct GuestInput<E: TxEssence> {
/// Base fee per gas
pub base_fee_per_gas: U256,
/// Taiko specific data
pub taiko: TaikoGuestInput,
pub taiko: TaikoGuestInput<E>,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct TaikoGuestInput<E: TxEssence> {
pub chain_spec_name: String,
pub l1_header: Header,
pub tx_list: Vec<u8>,
pub anchor_tx: Option<Transaction<E>>,
pub block_proposed: BlockProposed,
pub prover_data: TaikoProverData,
pub tx_blob_hash: Option<B256>,
}

#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct TaikoProverData {
pub prover: Address,
pub graffiti: B256,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum GuestOutput {
Success((Header, FixedBytes<32>)),
Failure,
}

sol! {
Expand Down Expand Up @@ -300,28 +323,6 @@ impl From<protocol_testnet::BlockProposed> for BlockProposed {
}
}

#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct TaikoProverData {
pub prover: Address,
pub graffiti: B256,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct TaikoGuestInput {
pub chain_spec_name: String,
pub l1_header: Header,
pub tx_list: Vec<u8>,
pub block_proposed: BlockProposed,
pub prover_data: TaikoProverData,
pub tx_blob_hash: Option<B256>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum GuestOutput {
Success((Header, FixedBytes<32>)),
Failure,
}

#[cfg(test)]
mod tests {
use alloc::vec;
Expand Down
Loading

0 comments on commit ebcfdd4

Please sign in to comment.