1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::str;

extern "C" {
    fn print_str(ptr: *const u8, len: usize);

    // Allows this root state machine to upgrade in-place to a new WASM binary.
    // Calling `upgrade` will destroy all child instances.
    fn upgrade_code(code_ptr: *const u8, code_len: usize);
    fn execute_code(execute_msg_ptr: *const u8, execute_msg_len: usize);

    // Creates a child WASM instance using the specified binary.
    // Returns a remote reference to the WASM instance.
    // fn evaluate(ptr: *const u8, len: usize);

    // Persistent state interface
    fn get_length(length_result_ptr: *const usize, key_ptr: *const u8, key_len: usize);
    fn get_state(key_ptr: *const u8, key_len: usize, result_vec_ptr: *const u8);
    fn set_state(key_ptr: *const u8, key_len: usize, value_ptr: *const u8, value_len: usize);
}

pub fn print(msg: &str) {
    unsafe {
        print_str(msg.as_ptr(), msg.len());
    }
}

/**
 * Fetches the length of the value at the specified key.
 */
fn get_length_from_host(key: &[u8]) -> usize {
    let value_length: usize = 0;
    unsafe {
        let len_ptr: *const usize = &value_length;
        get_length(len_ptr, key.as_ptr(), key.len() as usize);
    }
    value_length
}

pub fn read<K: AsRef<[u8]>>(key: K) -> Option<Vec<u8>> {
    let value_length = get_length_from_host(key.as_ref());
    if value_length == 0 {
        return None;
    }
    let value_bytes = vec![0; value_length];

    // Tell the host to load up the value bytes for this key.
    unsafe {
        get_state(
            key.as_ref().as_ptr(),
            key.as_ref().len() as usize,
            value_bytes.as_ptr(),
        );
    }

    Some(value_bytes)
}

pub fn write<K: AsRef<[u8]>>(key: K, value: Vec<u8>) {
    unsafe {
        set_state(
            key.as_ref().as_ptr(),
            key.as_ref().len(),
            value.as_ptr(),
            value.len() as usize,
        )
    };
}

pub fn upgrade(code: Vec<u8>) {
    unsafe { upgrade_code(code.as_ptr(), code.len() as usize) };
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ExecutionMessage {
    pub code_key: Vec<u8>,
    pub store_key: Vec<u8>,
    pub entry_function_name: String,
}

pub fn execute(code_key: Vec<u8>, store_key: Vec<u8>, entry_function_name: &str) {
    let execute_msg = ExecutionMessage {
        code_key,
        store_key,
        entry_function_name: String::from(entry_function_name),
    };
    let execute_msg_bytes: Vec<u8> = bincode::serialize(&execute_msg).unwrap();
    unsafe {
        execute_code(execute_msg_bytes.as_ptr(), execute_msg_bytes.len() as usize);
    }
}

pub struct Child {
    code_key: Vec<u8>,
    store_key: Vec<u8>,
}

impl Child {
    pub fn new(code_key: Vec<u8>, store_key: Vec<u8>) -> Child {
        Child {
            code_key,
            store_key,
        }
    }

    pub fn get<K: AsRef<[u8]>>(&self, key: K) -> Option<Vec<u8>> {
        let current_store = read(&self.store_key);
        match current_store {
            Some(store_bytes) => {
                let store: HashMap<Vec<u8>, Vec<u8>> = bincode::deserialize(&store_bytes).unwrap();
                let value = store.get(&key.as_ref().to_vec());
                match value {
                    Some(val) => Some(val.to_vec()),
                    None => None,
                }
            }
            None => None,
        }
    }
    pub fn set<K: AsRef<[u8]>, V: AsRef<[u8]>>(&self, key: K, value: V) {
        let current_store = read(&self.store_key);
        let mut child_store = match current_store {
            Some(store_bytes) => {
                let deserialized_store: HashMap<Vec<u8>, Vec<u8>> =
                    bincode::deserialize(&store_bytes[..]).unwrap();
                deserialized_store
            }
            None => {
                let child_store: HashMap<Vec<u8>, Vec<u8>> = HashMap::new();
                child_store
            }
        };

        child_store.insert(key.as_ref().to_vec(), value.as_ref().to_vec());
        let serialized_store = bincode::serialize(&child_store).unwrap();
        write(&self.store_key, serialized_store);
    }
    pub fn call(&self, func_name: &str) {
        execute(self.code_key.clone(), self.store_key.clone(), func_name);
    }
}