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

Commit

Permalink
feat: custom block import stage that verifies Sierra -> CASM class in…
Browse files Browse the repository at this point in the history
…tegrity for declare transactions (#1530)
  • Loading branch information
m-kus authored Apr 29, 2024
1 parent 9d26a6f commit 2e00de4
Show file tree
Hide file tree
Showing 24 changed files with 4,139 additions and 124 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
- chore(db): changed the way hashes are encoded
- refacto: reusable Eth client config for settlement/DA/other tasks
- ci: add gomu gomu no gatling perfomrance test
- feat(runtime): moved StarkEvents from Substrate events to runtime storage
- feat(node): validate declare txs against local Sierra class in block import
queue
- feat(runtime): moved StarkEvents from Substrate
- feat(rpc/trace_api): add `trace_transaction`
- fix(docker): fix dockerfile for `madara-node`
Expand Down
35 changes: 35 additions & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ members = [
"crates/client/commitment-state-diff",
"crates/client/settlement",
"crates/client/eth-client",
"crates/client/starknet-block-import",
"starknet-rpc-test",
"da-test",
"starknet-e2e-test",
Expand Down Expand Up @@ -59,6 +60,7 @@ default-members = [
"crates/client/commitment-state-diff",
"crates/client/settlement",
"crates/client/eth-client",
"crates/client/starknet-block-import",
"starknet-test-utils",
]

Expand Down Expand Up @@ -190,6 +192,7 @@ mc-commitment-state-diff = { path = "crates/client/commitment-state-diff" }
mc-l1-messages = { path = "crates/client/l1-messages" }
mc-settlement = { path = "crates/client/settlement" }
mc-eth-client = { path = "crates/client/eth-client" }
mc-starknet-block-import = { path = "crates/client/starknet-block-import" }

# Madara runtime
madara-runtime = { path = "crates/runtime" }
Expand Down
2 changes: 1 addition & 1 deletion crates/client/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use starknet_api::hash::StarkHash;
mod da_db;
mod db_opening_utils;
mod messaging_db;
mod sierra_classes_db;
pub mod sierra_classes_db;
pub use messaging_db::LastSyncedEventBlock;
mod l1_handler_tx_fee;
mod meta_db;
Expand Down
52 changes: 52 additions & 0 deletions crates/client/starknet-block-import/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[package]
name = "mc-starknet-block-import"
version.workspace = true
edition.workspace = true
description = "Starknet specific block import logic"
homepage = "https://github.com/keep-starknet-strange/madara"
license = "MIT"
publish = false
repository = "https://github.com/keep-starknet-strange/madara"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
async-trait = "0.1"
log = { workspace = true }
num-bigint = { workspace = true }
thiserror = { workspace = true }

# Substrate primitives dependencies
sp-api = { workspace = true }
sp-consensus = { workspace = true }
sp-runtime = { workspace = true }

# Substrate client dependencies
sc-consensus = { workspace = true }
sc-rpc-api = { workspace = true }

# Starknet
blockifier = { workspace = true }
cairo-lang-starknet = { workspace = true }
cairo-lang-starknet-classes = { workspace = true }
cairo-lang-utils = { workspace = true }
cairo-vm = { workspace = true }
hex = { workspace = true }
madara-runtime = { workspace = true }
mc-db = { workspace = true }
mc-rpc = { workspace = true }
pallet-starknet = { workspace = true }
pallet-starknet-runtime-api = { workspace = true }
starknet-core = { workspace = true }
starknet_api = { workspace = true, features = [
"scale-info",
"parity-scale-codec",
] }

# Primitives
mp-felt = { workspace = true }
mp-transactions = { workspace = true, features = ["scale-info"] }

[dev-dependencies]
serde_json = { workspace = true }
50 changes: 50 additions & 0 deletions crates/client/starknet-block-import/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Starknet block import

This crate introduces a Starknet specific handler that can be added to the block
import pipeline. More specifically, it "wraps" the underlying block import logic
i.e. executes first in the queue.

Read more about block import pipeline:

- <https://docs.substrate.io/learn/transaction-lifecycle/#block-authoring-and-block-imports>
- <https://doc.deepernetwork.org/v3/advanced/block-import/>

The purpose of this custom block import logic is to do additional checks for
declare transactions. Despite the introduction of the safe intermediate
representation (Sierra) for Cairo, there's still a possibility of the following
attack:

- User crafts a malicious Cairo contract the execution of which cannot be proven
- User submits that transaction via a patched node that does not verify Sierra
classes
- The runtime does not have Sierra classes and therefore cannot check the
validiy either
- Sequencer fails to prove the execution and also cannot charge for the work
done => DoS attack vector

Read more about Sierra and the problem it addresses:

- <https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/cairo-and-sierra/>

Starknet block import solves the issue above as follows:

- Upon receiving a new block it searches for declare transactions
- For every declare transaction found, it tries to find according Sierra classes
in the local DB
- It tries to compile the class to check if they match the contract class from
the transaction
- The block import fails if there is at least one transaction with mismatching
class hashes

## Notes

Currently Sierra classes DB is populated when user submits RPC requests and
therefore the approch works for single node setup only. In order to make it work
in the multi-node setting, one needs to query missing Sierra classes from other
nodes via P2P (see
<https://github.com/starknet-io/starknet-p2p-specs/blob/main/p2p/proto/class.proto>)

Cairo compiler version mismatch can be a problem, e.g. if the version used by
Madara is lagging behind significantly it can fail to compile Sierra classes
obtained from the recent compilers. Similarly, old Sierra classes might not
compile because of the broken backward compatibility.
Loading

0 comments on commit 2e00de4

Please sign in to comment.