Skip to content

Commit

Permalink
feat(octez): implement execute_rollup_outbox_message
Browse files Browse the repository at this point in the history
  • Loading branch information
huancheng-trili committed Nov 21, 2024
1 parent 24324a0 commit db33dfa
Show file tree
Hide file tree
Showing 33 changed files with 1,672 additions and 17 deletions.
7 changes: 7 additions & 0 deletions crates/jstzd/src/task/octez_rollup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use anyhow::{anyhow, Result};
use async_trait::async_trait;
use octez::r#async::{
directory::Directory,
endpoint::Endpoint,
rollup::{OctezRollupConfig, RollupDataDir},
};
use serde::Deserialize;
Expand All @@ -23,6 +24,12 @@ pub struct OctezRollup {
_data_dir: Arc<Directory>,
}

impl OctezRollup {
pub fn rpc_endpoint(&self) -> &Endpoint {
&self.config.rpc_endpoint
}
}

#[derive(Debug, Deserialize)]
struct HealthCheckResponse {
healthy: bool,
Expand Down
2 changes: 1 addition & 1 deletion crates/jstzd/tests/contract_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use tokio::io::AsyncWriteExt;

#[tokio::test(flavor = "multi_thread")]
async fn built_contracts() {
let (_node, client, _baker) = utils::setup().await;
let (_node, client, _baker) = utils::setup(None).await;
let tmp_dir = TempDir::new().unwrap();
generate_bootstrap_contract_files(&client, tmp_dir.path()).await;
let contract_names = ["exchanger", "jstz_native_bridge"];
Expand Down
2 changes: 1 addition & 1 deletion crates/jstzd/tests/octez_baker_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use utils::{get_block_level, setup};

#[tokio::test(flavor = "multi_thread")]
async fn test_baker() {
let (mut octez_node, _, mut baker) = setup().await;
let (mut octez_node, _, mut baker) = setup(None).await;
let node_endpoint = octez_node.rpc_endpoint();

let _ = baker.kill().await;
Expand Down
196 changes: 192 additions & 4 deletions crates/jstzd/tests/octez_client_test.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
use anyhow::Context;
use jstz_crypto::public_key_hash::PublicKeyHash;
use jstzd::task::Task;
use octez::r#async::{
client::{OctezClient, OctezClientConfigBuilder, Signature},
endpoint::Endpoint,
protocol::{
BootstrapContract, BootstrapSmartRollup, ProtocolParameter,
ProtocolParameterBuilder, SmartRollupPvmKind,
},
};
use serde::Deserialize;
use serde_json::Value;
use std::{
fs::{read_to_string, remove_file},
io::Write,
path::Path,
};
use tempfile::{NamedTempFile, TempDir};
use tezos_crypto_rs::hash::SmartRollupHash;
use tokio::io::AsyncWriteExt;
mod utils;
use std::path::PathBuf;
use utils::{
activate_alpha, create_client, get_head_block_hash, get_operation_kind, get_request,
import_activator, setup, spawn_octez_node, ACTIVATOR_SECRET_KEY,
import_activator, poll, setup, spawn_octez_node, spawn_rollup, ACTIVATOR_SECRET_KEY,
};

fn read_file(path: &Path) -> Value {
Expand Down Expand Up @@ -242,7 +250,7 @@ async fn add_address() {

#[tokio::test(flavor = "multi_thread")]
async fn call_contract() {
let (mut octez_node, octez_client, mut baker) = setup().await;
let (mut octez_node, octez_client, mut baker) = setup(None).await;
let bootstrap1: String = "bootstrap1".to_string();
let contract = "KT1F3MuqvT9Yz57TgCS3EkDcKNZe9HpiavUJ".to_string();
let before = octez_client.get_balance(&contract).await.unwrap();
Expand All @@ -266,7 +274,7 @@ async fn call_contract() {

#[tokio::test(flavor = "multi_thread")]
async fn originate_contract_and_wait_for() {
let (mut octez_node, octez_client, mut baker) = setup().await;
let (mut octez_node, octez_client, mut baker) = setup(None).await;
let head = get_head_block_hash(&octez_node.rpc_endpoint().to_string()).await;

let mut config_file = NamedTempFile::new().unwrap();
Expand Down Expand Up @@ -327,7 +335,7 @@ async fn originate_contract_and_wait_for() {

#[tokio::test(flavor = "multi_thread")]
async fn send_rollup_inbox_message() {
let (mut octez_node, octez_client, mut baker) = setup().await;
let (mut octez_node, octez_client, mut baker) = setup(None).await;

let (block, op) = octez_client
.send_rollup_inbox_message("bootstrap1", "0000", Some(0.1))
Expand All @@ -351,3 +359,183 @@ async fn send_rollup_inbox_message() {
let _ = baker.kill().await;
let _ = octez_node.kill().await;
}

#[derive(Deserialize)]
struct OutputProof {
pub commitment: String,
pub proof: String,
}

#[tokio::test(flavor = "multi_thread")]
async fn execute_rollup_outbox_message() {
let rollup_address = "sr1Uuiucg1wk5aovEY2dj1ZBsqjwxndrSaao";
// this is the destination contract where the outbox messages target
// this address is sealed in the rollup code
let contract_address = "KT1TFAweS9bMBetdDB3ndFicJWAEMb8MtSrK";
let installer_path = Path::new(std::env!("CARGO_MANIFEST_DIR")).join(format!(
"tests/resources/rollup/{rollup_address}/installer.hex"
));
let preimages_dir = Path::new(std::env!("CARGO_MANIFEST_DIR"))
.join(format!("tests/resources/rollup/{rollup_address}/preimages"));
let contract_path = Path::new(std::env!("CARGO_MANIFEST_DIR"))
.join(format!("tests/resources/contract/{contract_address}.json"));
let params = set_up_parameters_for_outbox_message(
rollup_address,
contract_address,
&installer_path,
&contract_path,
)
.await;

let (mut octez_node, octez_client, mut baker) =
setup(Some(params.parameter_file().path().to_path_buf())).await;
let mut rollup = spawn_rollup(
&octez_node,
&octez_client,
installer_path,
preimages_dir,
Some(rollup_address),
)
.await;

octez_client
.send_rollup_inbox_message("bootstrap1", "0000", Some(0.1))
.await
.unwrap();

// wait until outbox message is cemented
let proof = wait_for_outbox_proof(&rollup.rpc_endpoint().to_string())
.await
.unwrap();

let (block, op) = octez_client
.execute_rollup_outbox_message(
&SmartRollupHash::from_base58_check(rollup_address).unwrap(),
"bootstrap1",
&proof.commitment,
&format!("0x{}", &proof.proof),
Some(0.1),
)
.await
.unwrap();

tokio::time::timeout(
tokio::time::Duration::from_secs(5),
octez_client.wait_for(&op, Some(&block), None),
)
.await
.expect("wait_for should complete soon enough")
.expect("wait_for should be able to find the operation");

let operation_kind =
get_operation_kind(&octez_node.rpc_endpoint().to_string(), &block, &op)
.await
.unwrap();
assert_eq!(operation_kind, "smart_rollup_execute_outbox_message");

let _ = rollup.kill().await;
let _ = baker.kill().await;
let _ = octez_node.kill().await;
}

async fn set_up_parameters_for_outbox_message(
rollup_address: &str,
contract_address: &str,
installer_path: &PathBuf,
contract_path: &PathBuf,
) -> ProtocolParameter {
let kernel = String::from_utf8(
tokio::fs::read(&installer_path)
.await
.unwrap_or_else(|e| panic!("failed to read installer file: {:?}", e)),
)
.unwrap();
let contract_json = serde_json::from_slice(
&tokio::fs::read(&contract_path)
.await
.unwrap_or_else(|e| panic!("failed to read contract file: {:?}", e)),
)
.unwrap();
let params = ProtocolParameterBuilder::new()
.set_bootstrap_smart_rollups([BootstrapSmartRollup::new(
rollup_address,
SmartRollupPvmKind::Wasm,
&kernel,
serde_json::json!({"prim": "bytes"}),
)
.unwrap()])
.set_bootstrap_contracts([BootstrapContract::new(
contract_json,
1_000_000,
Some(contract_address),
)
.unwrap()])
.set_source_path(
Path::new(std::env!("CARGO_MANIFEST_DIR"))
.join("tests/sandbox-params.json")
.to_str()
.unwrap(),
)
.build()
.unwrap();

let mut content = tokio::fs::read_to_string(params.parameter_file().path())
.await
.unwrap();
let mut value: serde_json::Value = serde_json::from_str(&content).unwrap();

// overwriting these config values so that outbox messages get cemented sooner
value.as_object_mut().unwrap().insert(
"smart_rollup_challenge_window_in_blocks".to_owned(),
serde_json::json!(8),
);
value.as_object_mut().unwrap().insert(
"smart_rollup_commitment_period_in_blocks".to_owned(),
serde_json::json!(8),
);

content = serde_json::to_string(&value).unwrap();
tokio::fs::File::create(params.parameter_file().path())
.await
.unwrap()
.write_all(content.as_bytes())
.await
.unwrap();

params
}

async fn wait_for_outbox_proof(rollup_rpc_endpoint: &str) -> anyhow::Result<OutputProof> {
#[derive(Deserialize)]
struct Message {
message_index: u32,
}
#[derive(Deserialize)]
struct Executable {
outbox_level: u32,
messages: Vec<Message>,
}

let url = format!("{rollup_rpc_endpoint}/local/outbox/pending/executable");
let (outbox_level, message_index) = poll(30, 1000, || async {
// response: [{"outbox_level": 1, "messages": [{"message_index": 0, ...}, {"message_index": 1, ...}]}]
let res = reqwest::get(&url).await.ok()?;
let vs = res.json::<Vec<Executable>>().await.unwrap();
// using the first message here since any of those should work
let v = vs.first()?;
let m = v.messages.first()?;
Some((v.outbox_level, m.message_index))
})
.await
.expect("should be able to find outbox message soon enough");

let url = format!("{rollup_rpc_endpoint}/global/block/head/helpers/proofs/outbox/{outbox_level}/messages?index={message_index}");
let res = reqwest::get(&url)
.await
.context("failed to call rollup RPC endpoint")?;
let v = res
.json::<OutputProof>()
.await
.context("failed to parse response of rollup outbox proof RPC")?;
Ok(v)
}
10 changes: 8 additions & 2 deletions crates/jstzd/tests/octez_rollup_test.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
mod utils;
use jstzd::task::Task;
use std::path::Path;
use utils::{setup, spawn_rollup};

#[tokio::test(flavor = "multi_thread")]
async fn test_rollup() {
let (mut octez_node, client, mut baker) = setup().await;
let mut rollup = spawn_rollup(&octez_node, &client).await;
let (mut octez_node, client, mut baker) = setup(None).await;
let kernel_installer = Path::new(std::env!("CARGO_MANIFEST_DIR"))
.join("tests/toy_rollup/kernel_installer");
let preimages_dir =
Path::new(std::env!("CARGO_MANIFEST_DIR")).join("tests/toy_rollup/preimages");
let mut rollup =
spawn_rollup(&octez_node, &client, kernel_installer, preimages_dir, None).await;
let _ = rollup.kill().await;
// Should get an error since the rollup node should have been terminated
let rollup_is_alive = rollup.health_check().await;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"code": [
{
"args": [{ "annots": ["%myEntryPoint"], "prim": "int" }],
"prim": "parameter"
},
{
"args": [
{
"args": [
{ "annots": ["%myParameter1"], "prim": "int" },
{ "annots": ["%myParameter2"], "prim": "int" }
],
"prim": "pair"
}
],
"prim": "storage"
},
{
"args": [
[
{ "prim": "UNPAIR" },
{ "args": [{ "prim": "int" }, { "int": "123" }], "prim": "PUSH" },
{ "args": [{ "int": "3" }], "prim": "DUP" },
{ "prim": "CAR" },
{ "prim": "COMPARE" },
{ "prim": "LE" },
{
"args": [
[],
[
{
"args": [
{ "prim": "string" },
{
"string": "Assert failure: self.data.myParameter1 <= 123"
}
],
"prim": "PUSH"
},
{ "prim": "FAILWITH" }
]
],
"prim": "IF"
},
{ "prim": "SWAP" },
{ "prim": "DUP" },
{ "prim": "CAR" },
{ "args": [{ "int": "2" }], "prim": "DIG" },
{ "prim": "ADD" },
{ "args": [{ "int": "1" }], "prim": "UPDATE" },
{ "args": [{ "prim": "operation" }], "prim": "NIL" },
{ "prim": "PAIR" }
]
],
"prim": "code"
}
],
"storage": { "args": [{ "int": "1" }, { "int": "0" }], "prim": "Pair" }
}
Loading

0 comments on commit db33dfa

Please sign in to comment.