Skip to content

Commit

Permalink
feat(tee): use hex serialization for RPC responses
Browse files Browse the repository at this point in the history
Following Anton's suggestion, we have switched to hex serialization for
API/RPC requests and responses. Previously, we used default JSON
serialization for Vec<u8>, which resulted in a lengthy comma-separated
list of integers.

This change standardizes serialization, making it more efficient and
reducing the size of the responses. The previous format, with a series
of comma-separated integers for pubkey-like fields, looked odd.

Then:
```
curl -X POST\
     -H "Content-Type: application/json" \
     --data '{"jsonrpc": "2.0", "id": 1, "method": "unstable_getTeeProofs", "params": [491882, "sgx"] }' \
        https://mainnet.era.zksync.io
{"jsonrpc":"2.0","result":[{"attestation":[3,0,2,0,0,0,0,0,10,<dozens of comma-separated integers here>
```

Now:
```
$ curl -X POST \
       -H "Content-Type: application/json" \
       --data '{"jsonrpc": "2.0", "id": 1, "method": "unstable_getTeeProofs", "params": [1, "sgx"] }' \
          http://localhost:3050
{"jsonrpc":"2.0","result":[{"l1BatchNumber":1,"teeType":"sgx","pubkey":"0506070809","signature":"0001020304","proof":"0a0b0c0d0e","provedAt":"2024-09-16T11:53:38.253033Z","attestation":"0403020100"}],"id":1}
```

This change needs to be deployed in lockstep with:
matter-labs/teepot#209.
  • Loading branch information
pbeza committed Sep 18, 2024
1 parent 8729270 commit 6529958
Show file tree
Hide file tree
Showing 12 changed files with 96 additions and 8 deletions.
1 change: 1 addition & 0 deletions 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 core/lib/prover_interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ circuit_sequencer_api_1_5_0.workspace = true

serde.workspace = true
strum = { workspace = true, features = ["derive"] }
serde_with = { workspace = true, features = ["base64"] }
serde_with = { workspace = true, features = ["base64", "hex"] }
chrono = { workspace = true, features = ["serde"] }

[dev-dependencies]
Expand Down
4 changes: 4 additions & 0 deletions core/lib/prover_interface/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! This module defines the types used in the API.

use serde::{Deserialize, Serialize};
use serde_with::{hex::Hex, serde_as};
use zksync_types::{
protocol_version::{L1VerifierConfig, ProtocolSemanticVersion},
tee_types::TeeType,
Expand Down Expand Up @@ -71,8 +72,11 @@ pub struct VerifyProofRequest(pub Box<L1BatchProofForL1>);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct SubmitTeeProofRequest(pub Box<L1BatchTeeProofForL1>);

#[serde_as]
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct RegisterTeeAttestationRequest {
#[serde_as(as = "Hex")]
pub attestation: Vec<u8>,
#[serde_as(as = "Hex")]
pub pubkey: Vec<u8>,
}
5 changes: 5 additions & 0 deletions core/lib/prover_interface/src/outputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use core::fmt;

use circuit_sequencer_api_1_5_0::proof::FinalProof;
use serde::{Deserialize, Serialize};
use serde_with::{hex::Hex, serde_as};
use zksync_object_store::{serialize_using_bincode, Bucket, StoredObject};
use zksync_types::{protocol_version::ProtocolSemanticVersion, tee_types::TeeType, L1BatchNumber};

Expand All @@ -14,14 +15,18 @@ pub struct L1BatchProofForL1 {
}

/// A "final" TEE proof that can be sent to the L1 contract.
#[serde_as]
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct L1BatchTeeProofForL1 {
// signature generated within the TEE enclave, using the privkey corresponding to the pubkey
#[serde_as(as = "Hex")]
pub signature: Vec<u8>,
// pubkey used for signature verification; each key pair is attested by the TEE attestation
// stored in the db
#[serde_as(as = "Hex")]
pub pubkey: Vec<u8>,
// data that was signed
#[serde_as(as = "Hex")]
pub proof: Vec<u8>,
// type of TEE used for attestation
pub tee_type: TeeType,
Expand Down
6 changes: 3 additions & 3 deletions core/lib/prover_interface/tests/job_serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ fn test_proof_request_serialization() {
#[test]
fn test_tee_proof_request_serialization() {
let tee_proof_str = r#"{
"signature": [ 0, 1, 2, 3, 4 ],
"pubkey": [ 5, 6, 7, 8, 9 ],
"proof": [ 10, 11, 12, 13, 14 ],
"signature": "0001020304",
"pubkey": "0506070809",
"proof": "0A0B0C0D0E",
"tee_type": "sgx"
}"#;
let tee_proof_result = serde_json::from_str::<SubmitTeeProofRequest>(tee_proof_str).unwrap();
Expand Down
1 change: 1 addition & 0 deletions core/lib/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ once_cell.workspace = true
rlp.workspace = true
serde.workspace = true
serde_json.workspace = true
serde_with = { workspace = true, features = ["hex"] }
bigdecimal.workspace = true
strum = { workspace = true, features = ["derive"] }
thiserror.workspace = true
Expand Down
6 changes: 6 additions & 0 deletions core/lib/types/src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use chrono::{DateTime, Utc};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Value;
use serde_with::{hex::Hex, serde_as};
use strum::Display;
use zksync_basic_types::{
tee_types::TeeType,
Expand Down Expand Up @@ -784,15 +785,20 @@ pub struct Proof {
pub storage_proof: Vec<StorageProof>,
}

#[serde_as]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TeeProof {
pub l1_batch_number: L1BatchNumber,
pub tee_type: Option<TeeType>,
#[serde_as(as = "Option<Hex>")]
pub pubkey: Option<Vec<u8>>,
#[serde_as(as = "Option<Hex>")]
pub signature: Option<Vec<u8>>,
#[serde_as(as = "Option<Hex>")]
pub proof: Option<Vec<u8>>,
pub proved_at: DateTime<Utc>,
#[serde_as(as = "Option<Hex>")]
pub attestation: Option<Vec<u8>>,
}

Expand Down
2 changes: 1 addition & 1 deletion core/node/api_server/src/web3/testonly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ async fn spawn_server(
let (pub_sub_events_sender, pub_sub_events_receiver) = mpsc::unbounded_channel();

let mut namespaces = Namespace::DEFAULT.to_vec();
namespaces.extend([Namespace::Debug, Namespace::Snapshots]);
namespaces.extend([Namespace::Debug, Namespace::Snapshots, Namespace::Unstable]);

let server_builder = match transport {
ApiTransportLabel::Http => ApiBuilder::jsonrpsee_backend(api_config, pool).http(0),
Expand Down
1 change: 1 addition & 0 deletions core/node/api_server/src/web3/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ use crate::web3::testonly::{spawn_http_server, spawn_ws_server};
mod debug;
mod filters;
mod snapshots;
mod unstable;
mod vm;
mod ws;

Expand Down
69 changes: 69 additions & 0 deletions core/node/api_server/src/web3/tests/unstable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//! Tests for the `unstable` Web3 namespace.

use zksync_types::tee_types::TeeType;
use zksync_web3_decl::namespaces::UnstableNamespaceClient;

use super::*;

#[derive(Debug)]
struct GetTeeProofsTest {}

impl GetTeeProofsTest {
fn new() -> Self {
Self {}
}
}

#[async_trait]
impl HttpTest for GetTeeProofsTest {
async fn test(
&self,
client: &DynClient<L2>,
pool: &ConnectionPool<Core>,
) -> anyhow::Result<()> {
let batch_no = L1BatchNumber(1337);
let tee_type = TeeType::Sgx;
let proof = client.tee_proofs(batch_no, Some(tee_type)).await?;

assert!(proof.is_empty());

let mut storage = pool.connection().await.unwrap();
storage
.tee_verifier_input_producer_dal()
.create_tee_verifier_input_producer_job(batch_no)
.await?;

let pubkey = vec![0xDE, 0xAD, 0xBE, 0xEF];
let attestation = vec![0xC0, 0xFF, 0xEE];
let mut tee_proof_generation_dal = storage.tee_proof_generation_dal();
tee_proof_generation_dal
.save_attestation(&pubkey, &attestation)
.await?;
tee_proof_generation_dal
.insert_tee_proof_generation_job(batch_no, tee_type)
.await?;

let signature = vec![0, 1, 2, 3, 4];
let proof_vec = vec![5, 6, 7, 8, 9];
tee_proof_generation_dal
.save_proof_artifacts_metadata(batch_no, tee_type, &pubkey, &signature, &proof_vec)
.await?;

let proofs = client.tee_proofs(batch_no, Some(tee_type)).await?;
assert!(proofs.len() == 1);
let proof = &proofs[0];
assert!(proof.l1_batch_number == batch_no);
assert!(proof.tee_type == Some(tee_type));
assert!(proof.pubkey.as_ref() == Some(&pubkey));
assert!(proof.signature.as_ref() == Some(&signature));
assert!(proof.proof.as_ref() == Some(&proof_vec));
assert!(proof.attestation.as_ref() == Some(&attestation));

Ok(())
}
}

#[tokio::test]
async fn get_tee_proofs() {
test_http_server(GetTeeProofsTest::new()).await;
}
6 changes: 3 additions & 3 deletions core/node/proof_data_handler/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ async fn submit_tee_proof() {
// send a request to the /tee/submit_proofs endpoint, using a mocked TEE proof

let tee_proof_request_str = r#"{
"signature": [ 0, 1, 2, 3, 4 ],
"pubkey": [ 5, 6, 7, 8, 9 ],
"proof": [ 10, 11, 12, 13, 14 ],
"signature": "0001020304",
"pubkey": "0506070809",
"proof": "0A0B0C0D0E",
"tee_type": "sgx"
}"#;
let tee_proof_request =
Expand Down
1 change: 1 addition & 0 deletions prover/Cargo.lock

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

0 comments on commit 6529958

Please sign in to comment.