Skip to main content

Module sui::accumulator_settlement

use std::ascii;
use std::bcs;
use std::option;
use std::string;
use std::vector;
use sui::accumulator;
use sui::accumulator_metadata;
use sui::address;
use sui::bag;
use sui::bcs;
use sui::dynamic_field;
use sui::hash;
use sui::hex;
use sui::object;
use sui::party;
use sui::transfer;
use sui::tx_context;
use sui::vec_map;

Struct EventStreamHead

public struct EventStreamHead has store
Click to open
Fields
mmr: vector<u256>
Merkle Mountain Range of all events in the stream.
checkpoint_seq: u64
Checkpoint sequence number at which the event stream was written.
num_events: u64
Number of events in the stream.

Constants

const ENotSystemAddress: u64 = 0;
const EInvalidSplitAmount: u64 = 1;

Function settlement_prologue

Called by settlement transactions to ensure that the settlement transaction has a unique digest.

fun settlement_prologue(_accumulator_root: &mut sui::accumulator::AccumulatorRoot, _epoch: u64, _checkpoint_height: u64, _idx: u64, input_sui: u64, output_sui: u64, ctx: &sui::tx_context::TxContext)
Click to open
Implementation
fun settlement_prologue(
    _accumulator_root: &mut AccumulatorRoot,
    _epoch: u64,
    _checkpoint_height: u64,
    _idx: u64,
    // Total input sui received from user transactions
    input_sui: u64,
    // Total output sui withdrawn by user transactions
    output_sui: u64,
    ctx: &TxContext,
) {
    assert!(ctx.sender() == @0x0, ENotSystemAddress);
    record_settlement_sui_conservation(input_sui, output_sui);
}

Function settle_u128

fun settle_u128<T>(accumulator_root: &mut sui::accumulator::AccumulatorRoot, owner: address, merge: u128, split: u128, ctx: &mut sui::tx_context::TxContext)
Click to open
Implementation
fun settle_u128<T>(
    accumulator_root: &mut AccumulatorRoot,
    owner: address,
    merge: u128,
    split: u128,
    ctx: &mut TxContext,
) {
    assert!(ctx.sender() == @0x0, ENotSystemAddress);
    // Merge and split should be netted out prior to calling this function.
    assert!((merge == 0 ) != (split == 0), EInvalidSplitAmount);
    let name = accumulator_key<T>(owner);
    if (accumulator_root.has_accumulator<T, U128>(name)) {
        let is_zero = {
            let value: &mut U128 = accumulator_root.borrow_accumulator_mut(name);
            value.update(merge, split);
            value.is_zero()
        };
        if (is_zero) {
            let value = accumulator_root.remove_accumulator<T, U128>(name);
            destroy_u128(value);
            accumulator_root.remove_metadata<T>(owner);
        }
    } else {
        // cannot split if the field does not yet exist
        assert!(split == 0, EInvalidSplitAmount);
        let value = create_u128(merge);
        accumulator_root.add_accumulator(name, value);
        accumulator_root.create_metadata<T>(owner, ctx);
    };
}

Function record_settlement_sui_conservation

Called by the settlement transaction to track conservation of SUI.

fun record_settlement_sui_conservation(input_sui: u64, output_sui: u64)
Click to open
Implementation
native fun record_settlement_sui_conservation(input_sui: u64, output_sui: u64);

Function add_to_mmr

fun add_to_mmr(new_val: u256, mmr: &mut vector<u256>)
Click to open
Implementation
fun add_to_mmr(new_val: u256, mmr: &mut vector<u256>) {
    let mut i = 0;
    let mut cur = new_val;
    while (i < vector::length(mmr)) {
        let r = vector::borrow_mut(mmr, i);
        if (*r == 0) {
            *r = cur;
            return
        } else {
            cur = hash_two_to_one_u256(*r, cur);
            *r = 0;
        };
        i = i + 1;
    };
    // Vector length insufficient. Increase by 1.
    vector::push_back(mmr, cur);
}

Function u256_from_bytes

fun u256_from_bytes(bytes: vector<u8>): u256
Click to open
Implementation
fun u256_from_bytes(bytes: vector<u8>): u256 {
    bcs::new(bytes).peel_u256()
}

Function hash_two_to_one_u256

fun hash_two_to_one_u256(left: u256, right: u256): u256
Click to open
Implementation
fun hash_two_to_one_u256(left: u256, right: u256): u256 {
    let left_bytes = bcs::to_bytes(&left);
    let right_bytes = bcs::to_bytes(&right);
    let mut concatenated = left_bytes;
    vector::append(&mut concatenated, right_bytes);
    u256_from_bytes(hash::blake2b256(&concatenated))
}

Function new_stream_head

fun new_stream_head(new_root: u256, event_count_delta: u64, checkpoint_seq: u64): sui::accumulator_settlement::EventStreamHead
Click to open
Implementation
fun new_stream_head(new_root: u256, event_count_delta: u64, checkpoint_seq: u64): EventStreamHead {
    let mut initial_mmr = vector::empty();
    add_to_mmr(new_root, &mut initial_mmr);
    EventStreamHead {
        mmr: initial_mmr,
        checkpoint_seq: checkpoint_seq,
        num_events: event_count_delta,
    }
}

Function settle_events

entry fun settle_events(accumulator_root: &mut sui::accumulator::AccumulatorRoot, stream_id: address, new_root: u256, event_count_delta: u64, checkpoint_seq: u64, ctx: &sui::tx_context::TxContext)
Click to open
Implementation
entry fun settle_events(
    accumulator_root: &mut AccumulatorRoot,
    stream_id: address,
    new_root: u256,
    event_count_delta: u64,
    checkpoint_seq: u64,
    ctx: &TxContext,
) {
    assert!(ctx.sender() == @0x0, ENotSystemAddress);
    let name = accumulator_key<EventStreamHead>(stream_id);
    if (accumulator_root.has_accumulator<EventStreamHead, EventStreamHead>(copy name)) {
        let head: &mut EventStreamHead = accumulator_root.borrow_accumulator_mut(name);
        add_to_mmr(new_root, &mut head.mmr);
        head.num_events = head.num_events + event_count_delta;
        head.checkpoint_seq = checkpoint_seq;
    } else {
        let head = new_stream_head(new_root, event_count_delta, checkpoint_seq);
        accumulator_root.add_accumulator(name, head);
    };
}