Skip to content

Commit

Permalink
starknet tx, tx receipt support (#13)
Browse files Browse the repository at this point in the history
* wip

* wip

* wip

* wipd

* proof/verify abstract

* cleaner

* dependency to sn-trie

* omg it works

* update test cases

* wip

* abstract bitvec, clean up test, embed gateway

* quick update with poseidon

* feat: tx support done

* wip clean up

* ci: add sub rpc

* folder structure change

* sketch refactoring

* image

* alter dependency

* receipt support

* chore: minor

* readme

* sub rpc
  • Loading branch information
rkdud007 authored Sep 16, 2024
1 parent b5abb2a commit e679185
Show file tree
Hide file tree
Showing 23 changed files with 1,630 additions and 555 deletions.
1,042 changes: 599 additions & 443 deletions Cargo.lock

Large diffs are not rendered by default.

33 changes: 14 additions & 19 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
[package]
name = "eth-trie-proofs"
version = "0.1.1"
edition = "2021"
description = "Ethereum Transaction Trie Proofs"
readme = "README.md"
license-file = "LICENSE"
repository = "https://github.com/HerodotusDev/eth-trie-proofs"
keywords = ["mpt", "trie", "ethereum"]
categories = ["cryptography", "data-structures", "blockchain"]
exclude = [".github"]
[workspace]
resolver = "2"
members = ["cli", "crates/eth-trie-proofs", "crates/sn-trie-proofs"]

[workspace.dependencies]
eth-trie-proofs = { path = "crates/eth-trie-proofs" }
sn-trie-proofs = { path = "crates/sn-trie-proofs" }

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tokio = { version = "1.36.0", features = ["rt", "rt-multi-thread", "macros"] }
alloy-primitives = { version = "0.7.6" }
alloy = { version = "0.1.1", features = [
Expand All @@ -29,7 +21,7 @@ alloy = { version = "0.1.1", features = [
"k256",
] }
url = "2.5.0"
reqwest = "0.11.26"
reqwest = { version = "0.11.26", features = ["json"] }
alloy-rlp = { version = "0.3.5" }
eth_trie = "0.4.0"
ethereum-types = "0.14.1"
Expand All @@ -38,7 +30,10 @@ serde = "1.0.197"
serde_with = { version = "3.7.0", features = ["hex"] }
serde_json = "1.0.114"
thiserror = "1.0"

[[bin]]
name = "etp-cli"
path = "src/bin/cli.rs"
starknet-types-core = { version = "0.1.0", default-features = false, features = [
"serde",
"hash",
] }
starknet-types-rpc = { version = "0.7.1", git = "https://github.com/starknet-io/types-rs" }
sn-merkle-trie = { version = "0.1.0" }
bitflags = "2.6.0"
121 changes: 41 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,114 +1,75 @@
![](.github/readme.png)
# trie-proofs

# eth-trie-proofs
A comprehensive proofs handler for Ethereum and Starknet tries. This repository provides proof-building functionalities and includes a CLI tool.

A comprehensive proofs handler for Ethereum trie. Tested with various EIPs including Legacy, EIP-2930, EIP-1559, and EIP-4844. This repository exposes the proof building functionalities, and a CLI version.
## Supported Crates

## Features
- [x] [Ethereum Transaction/Receipt MPT Handler](./crates/eth-trie-proofs/README.md): Constructs transaction and receipt tries using a target block number or transaction hash, following Ethereum's Merkle Patricia Tree (MPT) specification.

- **Transaction Trie Handler**

- [x] Build a trie with a target block number
- [x] Build a trie with a target transaction hash
- [x] Retrieve proof by transaction index
- [x] Verify proof

- **Transaction Receipt Trie Handler**
- [x] Build a trie with a target block number
- [x] Build a trie with a target transaction hash
- [x] Retrieve proof by transaction index
- [x] Verify proof

## CLI Tool
The CLI tool supports generating proofs for transactions and receipts. Use the following commands based on your requirements:

Install with: `cargo install --path ./`
- [x] [Starknet Transaction/Receipt MPT Handler](./crates/sn-trie-proofs/README.md): Constructs transaction and receipt tries using a target block number, following Starknet's Merkle Patricia Tree (MPT) specification.

Or, run without installing: `cargo run --bin etp-cli`
## Trie Handler

- **Transaction Trie Handler**

**Generate a Proof via CLI**
- [x] Builds a trie with a target block number.
- [x] Builds a trie with a target transaction hash.
- [x] Retrieves proof by transaction index.
- [x] Verifies proof.

To generate a proof for a transaction, use the following command:
- **Transaction Receipt Trie Handler**

`etp-cli tx <TRANSACTION_HASH> [RPC_URL]`
- [x] Builds a trie with a target block number.
- [x] Builds a trie with a target transaction hash.
- [x] Retrieves proof by transaction index.
- [x] Verifies proof.

To generate a receipt proof:
## CLI Tool

`etp-cli receipt <TRANSACTION_HASH> [RPC_URL]`
_Currently only supports Ethereum MPT._

As a default, `https://ethereum-rpc.publicnode.com` is used as an RPC provider. This will probably work for recent transactions, but it is advised to use a dedicated RPC.
The CLI tool supports generating proofs for transactions and receipts. Use the following commands based on your requirements.

## Installation
### Installation

Add dependency `eth-trie-proofs` to your project:
Install the CLI tool using Cargo:

```shell
cargo install --path ./
```
eth-trie-proofs = { git = "https://github.com/HerodotusDev/eth-trie-proofs.git", branch = "main" }
```

## Example

### Building a Transaction Trie with a Target Block Number or Target Transaction Hash
Or run it without installing:

```rust
let target_tx_hash = B256::from(hex!(
"1fcb1196d8a3bff0bcf13309d2d2bb1a23ae1ac13f5674c801be0ff9254d5ab5"
));
```shell
cargo run --bin etp-cli
```

let mut txs_mpt_handler = TxsMptHandler::new(MAINNET_RPC_URL)?;
### Generate a Proof via CLI

txs_mpt_handler
.build_tx_tree_from_block(4370000)
.await?;
To generate a proof for a transaction:

let tx_index = txs_mpt_handler.tx_hash_to_tx_index(target_tx_hash)?;
let proof = txs_mpt_handler.get_proof(tx_index)?;
txs_mpt_handler
.verify_proof(tx_index, proof.clone())?;
```shell
etp-cli tx <TRANSACTION_HASH> [RPC_URL]
```

// You can either build with target tx hash. Both roots match.
let mut txs_mpt_handler2 = TxsMptHandler::new(MAINNET_RPC_URL)?;
txs_mpt_handler2
.build_tx_tree_from_tx_hash(target_tx_hash)
.await?;
To generate a receipt proof:

assert_eq!(
txs_mpt_handler.get_root().unwrap(),
txs_mpt_handler2.get_root().unwrap()
);
```shell
etp-cli receipt <TRANSACTION_HASH> [RPC_URL]
```

### Building a Transaction Receipts Trie with a Target Block Number

```rust
// 4844 transaction
let target_tx_hash = B256::from(hex!(
"9c1fbda4f649ac806ab0faefbe94e1a60282eb374ead6aa01bac042f52b28a8c"
));

let mut tx_receipts_mpt_handler = TxReceiptsMptHandler::new(MAINNET_RPC_URL)?;
tx_receipts_mpt_handler
.build_tx_receipts_tree_from_block(19426589)
.await?;

let tx_index = tx_receipts_mpt_handler
.tx_hash_to_tx_index(target_tx_hash)
.await?;
let proof = tx_receipts_mpt_handler.get_proof(tx_index)?;
tx_receipts_mpt_handler
.verify_proof(tx_index, proof.clone())?;
```
By default, `https://ethereum-rpc.publicnode.com` is used as the RPC provider. While this may work for recent transactions, it is advisable to use a dedicated RPC provider for better reliability.

### Credit
## Contributing

For trie implementation, this project depends on the [eth_trie](https://crates.io/crates/eth_trie).
For transaction and transaction receipt types, heavily depends on the [alloy](https://github.com/alloy-rs/alloy).
Contributions are welcome! If you'd like to contribute to this project, please fork the repository and submit a pull request. For major changes, please open an issue first to discuss what you would like to change.

## License

`eth-trie-proofs` is licensed under the [GNU General Public License v3.0](./LICENSE).
`trie-proofs` is licensed under the [GNU General Public License v3.0](./LICENSE).

---

Herodotus Dev Ltd - 2024

---
14 changes: 14 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "cli"
version = "0.1.0"
edition = "2021"

[dependencies]
eth-trie-proofs.workspace = true
tokio.workspace = true
clap.workspace = true
serde_with.workspace = true
serde.workspace = true
serde_json.workspace = true
alloy-primitives.workspace = true
url.workspace = true
File renamed without changes.
22 changes: 22 additions & 0 deletions crates/eth-trie-proofs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "eth-trie-proofs"
version = "0.1.1"
edition = "2021"
description = "Ethereum Transaction Trie Proofs"
readme = "README.md"
license-file = "LICENSE"
repository = "https://github.com/HerodotusDev/eth-trie-proofs"
keywords = ["mpt", "trie", "ethereum"]
categories = ["cryptography", "data-structures", "blockchain"]
exclude = [".github"]

[dependencies]
tokio.workspace = true
alloy-primitives.workspace = true
alloy.workspace = true
url.workspace = true
reqwest.workspace = true
alloy-rlp.workspace = true
eth_trie.workspace = true
ethereum-types.workspace = true
thiserror.workspace = true
81 changes: 81 additions & 0 deletions crates/eth-trie-proofs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# eth-trie-proofs

![CI](https://img.shields.io/github/actions/workflow/status/HerodotusDev/eth-trie-proofs/ci.yml?style=flat-square&logo=githubactions&logoColor=white&label=CI)
[![Crates.io](https://img.shields.io/crates/v/eth-trie-proofs?style=flat-square&logo=lootcrate)](https://crates.io/crates/eth-trie-proofs)
[![Documentation](https://img.shields.io/docsrs/eth-trie-proofs)](https://docs.rs/eth-trie-proofs)

![](.github/readme.png)

A comprehensive transaction/receipt inclusion proofs handler for [Ethereum trie](https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie/). Tested with various EIPs including Legacy, EIP-2930, EIP-1559, and EIP-4844. This library exposes various proof building functionalities, verification, trie construction etc.

## Installation

Add dependency `eth-trie-proofs` to your project:

```
eth-trie-proofs = { version= "0.1.1" }
```

## Usage

- **Transaction Trie Handler**

```rust
#[tokio::test]
async fn test_tx_mpt_frontier() {
let url = Url::parse(MAINNET_RPC_URL_SUB).unwrap();
let target_tx_hash = B256::from(hex!(
"5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"
));
let mut txs_mpt_handler = TxsMptHandler::new(url).unwrap();
txs_mpt_handler
.build_tx_tree_from_block(46147)
.await
.unwrap();
let tx_index = txs_mpt_handler.tx_hash_to_tx_index(target_tx_hash).unwrap();
let proof = txs_mpt_handler.get_proof(tx_index).unwrap();
txs_mpt_handler
.verify_proof(tx_index, proof.clone())
.unwrap();
}
```

- **Transaction Receipt Trie Handler**

```rust
#[tokio::test]
async fn test_tx_receipt_1559() {
let url = Url::parse(MAINNET_RPC_URL).unwrap();
let target_tx_hash = B256::from(hex!(
"2055b7e01304f87f9412cd44758cd248bc2da2dab95c97026064ffb084711735"
));

let mut tx_receipts_mpt_handler = TxReceiptsMptHandler::new(url).unwrap();
tx_receipts_mpt_handler
.build_tx_receipts_tree_from_block(12965000)
.await
.unwrap();

let tx_index = tx_receipts_mpt_handler
.tx_hash_to_tx_index(target_tx_hash)
.await
.unwrap();
let proof = tx_receipts_mpt_handler.get_proof(tx_index).unwrap();
tx_receipts_mpt_handler
.verify_proof(tx_index, proof.clone())
.unwrap();
}
```

### Credit

For trie implementation, this project depends on the [eth_trie](https://crates.io/crates/eth_trie).
For transaction and transaction receipt types, heavily depends on the [alloy](https://github.com/alloy-rs/alloy).

## License

`eth-trie-proofs` is licensed under the [GNU General Public License v3.0](../../LICENSE).

---

Herodotus Dev Ltd - 2024
6 changes: 0 additions & 6 deletions src/lib.rs → crates/eth-trie-proofs/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ use alloy::transports::{RpcError, TransportErrorKind};
use eth_trie::TrieError;
use thiserror::Error;

mod rpc;
pub mod tx;
pub mod tx_receipt;
pub mod tx_receipt_trie;
pub mod tx_trie;

#[derive(Error, Debug)]
pub enum EthTrieError {
#[error("Trie error: {0}")]
Expand Down
8 changes: 8 additions & 0 deletions crates/eth-trie-proofs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub mod error;
mod rpc;
pub mod tx;
pub mod tx_receipt;
pub mod tx_receipt_trie;
pub mod tx_trie;

pub use error::EthTrieError;
2 changes: 1 addition & 1 deletion src/rpc.rs → crates/eth-trie-proofs/src/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::EthTrieError;
use crate::error::EthTrieError;
use alloy::network::Ethereum;
use alloy::primitives::B256;
use alloy::providers::{Provider, RootProvider};
Expand Down
2 changes: 1 addition & 1 deletion src/tx.rs → crates/eth-trie-proofs/src/tx.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{EthTrieError, Field};
use crate::error::{EthTrieError, Field};
use alloy::consensus::{
SignableTransaction, TxEip1559, TxEip2930, TxEip4844, TxEnvelope, TxLegacy, TxType,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::EthTrieError;
use crate::error::EthTrieError;
use alloy::consensus::{Eip658Value, Receipt, ReceiptWithBloom, TxReceipt};
use alloy::consensus::{ReceiptEnvelope, TxType};
use alloy::eips::eip2718::Decodable2718;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use ethereum_types::H256;
use url::Url;

use crate::{
error::EthTrieError,
rpc::RpcProvider,
tx_receipt::{ConsensusTxReceipt, RpcTxReceipt},
EthTrieError,
};

/// Represents a handler for transactions Merkle Patricia Trie (MPT) operations,
Expand Down Expand Up @@ -169,6 +169,8 @@ mod tests {
use alloy::primitives::B256;

const MAINNET_RPC_URL: &str = "https://mainnet.infura.io/v3/720000a7936b45c79d0868f70478e2e9";
const MAINNET_RPC_URL2: &str =
"https://eth-mainnet.g.alchemy.com/v2/FZEXaYqCaVKtHHr0B6uPaTavacl9uDAX";

// Test cases
// Byzantium: 4370000
Expand Down Expand Up @@ -224,7 +226,7 @@ mod tests {

#[tokio::test]
async fn test_tx_receipt_1559() {
let url = Url::parse(MAINNET_RPC_URL).unwrap();
let url = Url::parse(MAINNET_RPC_URL2).unwrap();
let target_tx_hash = B256::from(hex!(
"2055b7e01304f87f9412cd44758cd248bc2da2dab95c97026064ffb084711735"
));
Expand Down
Loading

0 comments on commit e679185

Please sign in to comment.