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

feat: add delegate call voucher to libcmt #86

Merged
merged 4 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions fs/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ RUN apt-get update && \
bash=5.1-6ubuntu1.1 \
psmisc=23.4-2build3 \
bc=1.07.1-3build1 \
curl=7.81.0-1ubuntu1.18 \
curl=7.81.0-1ubuntu1.20 \
device-tree-compiler=1.6.1-1 \
jq=1.6-2.1ubuntu3 \
lua5.4=5.4.4-1 \
lua-socket=3.0~rc1+git+ac3201d-6 \
xxd=2:8.2.3995-1ubuntu2.19 \
xxd=2:8.2.3995-1ubuntu2.21 \
file=1:5.41-3ubuntu0.1 \
stress-ng=0.13.12-2ubuntu1 \
/tmp/${TOOLS_DEB} \
Expand Down
30 changes: 29 additions & 1 deletion rollup-http/rollup-http-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

use crate::rollup::{
AdvanceRequest, Exception, GIORequest, IndexResponse, InspectRequest, Notice, Report,
RollupRequest, RollupResponse, Voucher,
RollupRequest, RollupResponse, Voucher, DelegateCallVoucher,
};
use hyper::Response;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -59,6 +59,34 @@ pub async fn send_voucher(rollup_http_server_addr: &str, voucher: Voucher) {
}
}

pub async fn send_delegate_call_voucher(rollup_http_server_addr: &str, delegate_call_voucher: DelegateCallVoucher) {
log::debug!("sending delegate call voucher request to {}", rollup_http_server_addr);
let client = hyper::Client::new();
let req = hyper::Request::builder()
.method(hyper::Method::POST)
.header(hyper::header::CONTENT_TYPE, "application/json")
.uri(rollup_http_server_addr.to_string() + "/delegate-call-voucher")
.body(hyper::Body::from(serde_json::to_string(&delegate_call_voucher).unwrap()))
.expect("delegate call voucher request");
match client.request(req).await {
Ok(res) => {
let id_response = serde_json::from_slice::<IndexResponse>(
&hyper::body::to_bytes(res)
.await
.expect("error in voucher in response handling")
.to_vec(),
);
log::debug!("voucher generated: {:?}", &id_response);
}
Err(e) => {
log::error!(
"failed to send delegate call voucher request to rollup http server: {}",
e
);
}
}
}

pub async fn send_notice(rollup_http_server_addr: &str, notice: Notice) {
log::debug!("sending notice request to {}", rollup_http_server_addr);
let client = hyper::Client::new();
Expand Down
6 changes: 6 additions & 0 deletions rollup-http/rollup-http-client/src/rollup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ pub struct Voucher {
pub payload: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DelegateCallVoucher {
pub destination: String,
pub payload: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Report {
pub payload: String,
Expand Down
57 changes: 54 additions & 3 deletions rollup-http/rollup-http-server/src/http_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

use std::sync::Arc;

use actix_web::{middleware::Logger, web::Data, App, HttpResponse, HttpServer, http::header::CONTENT_TYPE};
use actix_web::{
http::header::CONTENT_TYPE, middleware::Logger, web::Data, App, HttpResponse, HttpServer,
};
use actix_web_validator::{Json, JsonConfig};
use async_mutex::Mutex;
use serde::{Deserialize, Serialize};
Expand All @@ -26,8 +28,8 @@ use tokio::sync::Notify;
use crate::config::Config;
use crate::rollup::{self, GIORequest, RollupFd};
use crate::rollup::{
AdvanceRequest, Exception, FinishRequest, InspectRequest, Notice, Report, RollupRequest,
Voucher,
AdvanceRequest, DelegateCallVoucher, Exception, FinishRequest, InspectRequest, Notice, Report,
RollupRequest, Voucher,
};

#[derive(Debug, Serialize, Deserialize)]
Expand All @@ -54,6 +56,7 @@ pub fn create_server(
.app_data(json_cfg)
.wrap(Logger::default())
.service(voucher)
.service(delegate_call_voucher)
.service(notice)
.service(report)
.service(gio)
Expand Down Expand Up @@ -116,6 +119,54 @@ async fn voucher(mut voucher: Json<Voucher>, data: Data<Mutex<Context>>) -> Http
};
}

/// Process voucher request from DApp, write voucher to rollup device
#[actix_web::post("/delegate-call-voucher")]
async fn delegate_call_voucher(
mut delegate_call_voucher: Json<DelegateCallVoucher>,
data: Data<Mutex<Context>>,
) -> HttpResponse {
log::debug!("received voucher request");
// Check if address is valid
if delegate_call_voucher.destination.len()
!= (rollup::CARTESI_ROLLUP_ADDRESS_SIZE * 2 + 2) as usize
|| (!delegate_call_voucher.destination.starts_with("0x"))
{
log::error!(
"address not valid: '{}' len: {}",
delegate_call_voucher.destination,
delegate_call_voucher.destination.len()
);
return HttpResponse::BadRequest()
.append_header((CONTENT_TYPE, "text/plain"))
.body("address not valid");
}
let context = data.lock().await;
// Write voucher to linux rollup device
return match rollup::rollup_write_delegate_call_voucher(
&*context.rollup_fd.lock().await,
&mut delegate_call_voucher.0,
) {
Ok(voucher_index) => {
log::debug!(
"delegate call voucher successfully inserted {:#?}",
delegate_call_voucher
);
HttpResponse::Created().json(IndexResponse {
index: voucher_index,
})
}
Err(e) => {
log::error!(
"unable to insert voucher, error details: '{}'",
e.to_string()
);
HttpResponse::BadRequest()
.append_header((CONTENT_TYPE, "text/plain"))
.body(format!("unable to insert voucher, error details: '{}'", e))
}
};
}

/// Process notice request from DApp, write notice to rollup device
#[actix_web::post("/notice")]
async fn notice(mut notice: Json<Notice>, data: Data<Mutex<Context>>) -> HttpResponse {
Expand Down
64 changes: 63 additions & 1 deletion rollup-http/rollup-http-server/src/rollup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,13 @@ pub struct Voucher {
pub payload: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct DelegateCallVoucher {
#[validate(regex(path = "*ETH_ADDR_REGEXP"))]
pub destination: String,
pub payload: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct Report {
pub payload: String,
Expand Down Expand Up @@ -455,7 +462,7 @@ pub fn rollup_write_voucher(

if res != 0 {
return Err(Box::new(RollupError::new(&format!(
"IOCTL_ROLLUP_WRITE_VOUCHER returned error {}",
"IOCTL_ROLLUP_WRITE_OUTPUT returned error {}",
res
))));
} else {
Expand All @@ -465,6 +472,46 @@ pub fn rollup_write_voucher(
Ok(voucher_index as u64)
}

pub fn rollup_write_delegate_call_voucher(
fd: &RollupFd,
delegate_call_voucher: &mut DelegateCallVoucher,
) -> Result<u64, Box<dyn std::error::Error>> {
print_delegate_call_voucher(delegate_call_voucher);

let mut binary_payload = match hex::decode(&delegate_call_voucher.payload[2..]) {
Ok(payload) => payload,
Err(_err) => {
return Err(Box::new(RollupError::new(&format!(
"Error decoding voucher payload, it must be in Ethereum hex binary format"
))));
}
};
let address = cmt_abi_address_t::from_hex(&delegate_call_voucher.destination[2..])?;
let payload = cmt_abi_bytes_t {
data: binary_payload.as_mut_ptr() as *mut c_void,
length: binary_payload.len(),
};

let mut voucher_index: std::os::raw::c_ulong = 0;
let res = unsafe {
cmt_rollup_emit_delegate_call_voucher(fd.0, &address, &payload, &mut voucher_index)
};

if res != 0 {
return Err(Box::new(RollupError::new(&format!(
"IOCTL_ROLLUP_WRITE_OUTPUT returned error {}",
res
))));
} else {
log::debug!(
"delegate call voucher with id {} successfully written!",
voucher_index
);
}

Ok(voucher_index as u64)
}

pub fn rollup_write_report(
fd: &RollupFd,
report: &Report,
Expand Down Expand Up @@ -714,6 +761,21 @@ pub fn print_voucher(voucher: &Voucher) {
log::debug!("{}", &voucher_request_printout);
}

pub fn print_delegate_call_voucher(delegate_call_voucher: &DelegateCallVoucher) {
let mut voucher_request_printout = String::new();
voucher_request_printout.push_str("voucher: {{ destination: ");
format_address_printout(
&delegate_call_voucher.destination,
&mut voucher_request_printout,
);
voucher_request_printout.push_str(&format!(
" length: {} payload: {} }}",
delegate_call_voucher.payload.len(),
delegate_call_voucher.payload
));
log::debug!("{}", &voucher_request_printout);
}

pub fn print_report(report: &Report) {
log::debug!(
"report: {{ length: {} payload: {}}}",
Expand Down
66 changes: 65 additions & 1 deletion rollup-http/rollup-http-server/tests/rollup-http-server-tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use actix_server::ServerHandle;
use async_mutex::Mutex;
use rand::Rng;
use rollup_http_client::rollup::{
Exception, GIORequest, Notice, Report, RollupRequest, RollupResponse, Voucher,
DelegateCallVoucher, Exception, GIORequest, Notice, Report, RollupRequest, RollupResponse,
Voucher,
};
use rollup_http_server::config::Config;
use rollup_http_server::rollup::RollupFd;
Expand Down Expand Up @@ -283,6 +284,69 @@ async fn test_write_voucher(
Ok(())
}

fn check_delegate_call_voucher_or_fail(
original_delegate_call_voucher: DelegateCallVoucher,
output_filename: &str,
) {
// we try to decode the produced voucher with a third-party lib to see if it matches
// the expected values
let data = std::fs::read(output_filename).expect("error reading voucher file");
let decoded_voucher = ethabi::decode(
&[ethabi::ParamType::Address, ethabi::ParamType::Bytes],
&data[4..], // skip the first 4 bytes that are the function signature
)
.ok()
.unwrap();

assert_eq!(
"0x".to_string() + &decoded_voucher[0].to_string(),
original_delegate_call_voucher.destination,
);
assert_eq!(
"0x".to_string() + &decoded_voucher[1].to_string(),
original_delegate_call_voucher.payload,
);
}

#[rstest]
#[tokio::test]
async fn test_write_delegate_call_voucher(
context_future: impl Future<Output = Context>,
) -> Result<(), Box<dyn std::error::Error>> {
let context = context_future.await;
println!("Writing delegate call voucher");
let test_delegate_call_voucher_01 = DelegateCallVoucher {
destination: "0x1111111111111111111111111111111111111111".to_string(),
payload: "0x".to_string() + &hex::encode("delegate call voucher test payload 01"),
};
let test_delegate_call_voucher_02 = DelegateCallVoucher {
destination: "0x2222222222222222222222222222222222222222".to_string(),
payload: "0x".to_string() + &hex::encode("delegate call voucher test payload 02"),
};
rollup_http_client::client::send_delegate_call_voucher(
&context.address,
test_delegate_call_voucher_01.clone(),
)
.await;

check_delegate_call_voucher_or_fail(test_delegate_call_voucher_01, "none.output-0.bin");
std::fs::remove_file("none.output-0.bin")?;

println!("Writing second voucher!");

rollup_http_client::client::send_delegate_call_voucher(
&context.address,
test_delegate_call_voucher_02.clone(),
)
.await;
context.server_handle.stop(true).await;

check_delegate_call_voucher_or_fail(test_delegate_call_voucher_02, "none.output-1.bin");
std::fs::remove_file("none.output-1.bin")?;

Ok(())
}

#[rstest]
#[tokio::test]
async fn test_write_notice(
Expand Down
16 changes: 16 additions & 0 deletions sys-utils/libcmt/include/libcmt/rollup.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,22 @@ void cmt_rollup_fini(cmt_rollup_t *me);
* |< 0| failure with a -errno value | */
int cmt_rollup_emit_voucher(cmt_rollup_t *me, const cmt_abi_address_t *address, const cmt_abi_u256_t *value, const cmt_abi_bytes_t *data, uint64_t *index);

/** Emit a delegate call voucher
*
* Equivalent to the `DelegateCallVoucher(address,bytes)` solidity call.
*
* @param [in,out] me initialized @ref cmt_rollup_t instance
* @param [in] address destination data
* @param [in] data message contents
* @param [out] index index of emitted voucher, if successful
*
* @return
* | | |
* |--:|-----------------------------|
* | 0| success |
* |< 0| failure with a -errno value | */
int cmt_rollup_emit_delegate_call_voucher(cmt_rollup_t *me, const cmt_abi_address_t *address, const cmt_abi_bytes_t *data, uint64_t *index);

/** Emit a notice
*
* @param [in,out] me initialized cmt_rollup_t instance
Expand Down
Loading
Loading