Skip to main content

Part 4: Using the entire slot

In some cases, you may want to retrieve the entire contents of a slot. For example, it can be convenient to get the entire slot because it has a fixed size, while the data in the slot may be smaller and padded to fit the slot.

Fetching and storing the full slot

Retrieving the full slot is similar to retrieving any data from the slot. In this case, you change the kernel to retrieve data of the exact size of the slot.

  1. Update the run function in the lib/rs file to this code:

    pub fn run<R: Runtime>(
    host: &mut R,
    param: &RollupDalParameters,
    slot_index: u8,
    ) -> Result<(), RuntimeError> {
    // Reading one message from the shared inbox is always safe,
    // because the shared inbox contains at least 3 messages per
    // Tezos block.
    let sol = host.read_input()?.unwrap();

    let target_level = sol.level as usize - param.attestation_lag as usize;

    let mut buffer = vec![0u8; param.slot_size as usize];

    let bytes_read = host.reveal_dal_page(target_level as i32, slot_index, 0, &mut buffer)?;

    if bytes_read == 0 {
    debug_msg!(
    host,
    "No attested slot at index {} for level {}\n",
    slot_index,
    target_level
    );

    return Ok(());
    }

    debug_msg!(
    host,
    "Attested slot at index {} for level {}\n",
    slot_index,
    target_level
    );

    let num_pages = param.slot_size / param.page_size;

    for page_index in 1..num_pages {
    let _result = host.reveal_dal_page(
    target_level as i32,
    slot_index,
    page_index.try_into().unwrap(),
    &mut buffer[page_index as usize * (param.page_size as usize)
    ..(page_index as usize + 1) * (param.page_size as usize)],
    );
    }

    let hash = blake2b::digest(&buffer, 32).unwrap();
    let key = hex::encode(hash);
    let path = OwnedPath::try_from(format!("/{}", key)).unwrap();

    debug_msg!(host, "Saving slot under `{}'\n", path);

    let () = host.store_write_all(&path, &buffer)?;

    Ok(())
    }

    Now the run function works like this:

    1. It allocates a buffer of the size of a slot, not a size of a page.
    2. It tries to fetch the contents of the first page. If 0 bytes are written by reveal_dal_page, the targeted slot has not been attested for this block.
    3. If the targeted slot has been attested, the function reads as many pages as necessary to get the full slot data.
    4. It stores the data in the durable storage, using the Blake2B hash (encoded in hexadecimal) as its key.
  2. Add these use statements to the beginning of the file:

    use tezos_crypto_rs::blake2b;
    use tezos_smart_rollup::storage::path::OwnedPath;

    These dependencies use tezos_crypto_rs for hashing, and hex for encoding.

  3. Add the matching dependencies to the Cargo.toml file:

    tezos_crypto_rs = { version = "0.5.2", default-features = false }
    hex = "0.4.3"

    Adding default-features = false for tezos_crypto_rs is necessary for the crate to be compatible with Smart Rollups.

  4. Deploy the Smart Rollup again, publish a file as you did in the previous section, and wait for enough levels to pass. The Smart Rollup log shows the hash of the data, as in this example:

    RollupDalParameters { number_of_slots: 32, attestation_lag: 4, slot_size: 65536, page_size: 4096 }
    Attested slot at index 10 for level 15482
    Saving slot under `/6a578d1e6746d29243ff81923bcea6375e9344d719ca118e14cd9f3d3b00cd96'
    See you in the next level
  5. Get the data from the slot by passing the hash, as in this example:

    hash=6a578d1e6746d29243ff81923bcea6375e9344d719ca118e14cd9f3d3b00cd96
    curl "http://localhost:8932/global/block/head/durable/wasm_2_0_0/value?key=/${hash}" \
    -H 'Content-Type: application/octet-stream' \
    -o slot.bin
  6. Inspect the contents of the slot by running this command:

    hexdump -C slot.bin

    For example, if you uploaded a file that contained the text "Hi! This is a message to go on the DAL." the slot might look like this:

    00000000  22 34 38 36 39 32 31 32  30 35 34 36 38 36 39 37  |"486921205468697|
    00000010 33 32 30 36 39 37 33 32 30 36 31 32 30 36 64 36 |32069732061206d6|
    00000020 35 37 33 37 33 36 31 36 37 36 35 32 30 37 34 36 |5737361676520746|
    00000030 66 32 30 36 37 36 66 32 30 36 66 36 65 32 30 37 |f20676f206f6e207|
    00000040 34 36 38 36 35 32 30 34 34 34 31 34 63 32 65 30 |468652044414c2e0|
    00000050 61 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 |a000000000000000|
    00000060 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 |0000000000000000|
    *
    00020000 30 22 0a |0".|
    00020003
Why diff won't work

You cannot use diff to ensure that the file you originally published and the one that you downloaded from the rollup node are equal. Indeed, they are not: because the size of a slot is fixed, the DAL node pads the value it receives from POST /slot in order to ensure that it has the correct size.

Next steps

Now you know how to send files to the DAL and use a Smart Rollup to store the data.

From there, the sky's the limit. You can implement many other features, such as:

  • Handling more than one file per level
  • Having file publishers pay for the storage that they are using in layer 2 by allowing them to deposit tez to the Smart Rollup and sign the files they publish
  • Building a frontend to visualize the files in the archive
  • Providing the original size of the file by modifying the script to prefix the file with its size