mod util;
use essential_state_read_vm::{
asm::{self, Op},
types::{convert::word_4_from_u8_32, ContentAddress},
GasLimit, Vm,
};
use util::*;
#[tokio::test]
async fn state_read_3_42s() {
let access = *test_access();
let state = State::new(vec![(
access
.solution
.this_data()
.predicate_to_solve
.contract
.clone(),
vec![
(vec![0, 0, 0, 0], vec![42]),
(vec![0, 0, 0, 1], vec![42]),
(vec![0, 0, 0, 2], vec![42]),
],
)]);
let mut vm = Vm::default();
let num_words = 3;
let ops = &[
asm::Stack::Push(num_words).into(),
asm::StateMemory::AllocSlots.into(),
asm::Stack::Push(0).into(), asm::Stack::Push(0).into(), asm::Stack::Push(0).into(), asm::Stack::Push(0).into(), asm::Stack::Push(4).into(), asm::Stack::Push(num_words).into(),
asm::Stack::Push(0).into(), asm::StateRead::KeyRange,
asm::TotalControlFlow::Halt.into(),
];
vm.exec_ops(ops, access, &state, &|_: &Op| 1, GasLimit::UNLIMITED)
.await
.unwrap();
assert_eq!(&vm.state_memory[..], &[vec![42], vec![42], vec![42]]);
assert_eq!(vm.state_memory.len(), 3);
}
#[tokio::test]
async fn state_read_some_none_some() {
let access = *test_access();
let state = State::new(vec![(
access
.solution
.this_data()
.predicate_to_solve
.contract
.clone(),
vec![(vec![0, 0, 0, 0], vec![42]), (vec![0, 0, 0, 2], vec![42])],
)]);
let mut vm = Vm::default();
let num_words = 3;
let ops = &[
asm::Stack::Push(num_words).into(),
asm::StateMemory::AllocSlots.into(),
asm::Stack::Push(0).into(), asm::Stack::Push(0).into(), asm::Stack::Push(0).into(), asm::Stack::Push(0).into(), asm::Stack::Push(4).into(), asm::Stack::Push(num_words).into(),
asm::Stack::Push(0).into(), asm::StateRead::KeyRange,
asm::TotalControlFlow::Halt.into(),
];
vm.exec_ops(ops, access, &state, &|_: &Op| 1, GasLimit::UNLIMITED)
.await
.unwrap();
assert_eq!(&vm.state_memory[..], &[vec![42], vec![], vec![42]]);
assert_eq!(vm.state_memory.len(), 3);
}
#[tokio::test]
async fn state_read_ext() {
let ext_contract_addr = ContentAddress([0x12; 32]);
let state = State::new(vec![(
ext_contract_addr.clone(),
vec![
(vec![1, 2, 3, 4], vec![40]),
(vec![1, 2, 3, 5], vec![41]),
(vec![1, 2, 3, 6], vec![42]),
],
)]);
let mut vm = Vm::default();
let num_words = 3;
let [addr0, addr1, addr2, addr3] = word_4_from_u8_32(ext_contract_addr.0);
let ops = &[
asm::Stack::Push(num_words).into(),
asm::StateMemory::AllocSlots.into(),
asm::Stack::Push(addr0).into(),
asm::Stack::Push(addr1).into(),
asm::Stack::Push(addr2).into(),
asm::Stack::Push(addr3).into(),
asm::Stack::Push(1).into(), asm::Stack::Push(2).into(), asm::Stack::Push(3).into(), asm::Stack::Push(4).into(), asm::Stack::Push(4).into(), asm::Stack::Push(num_words).into(),
asm::Stack::Push(0).into(), asm::StateRead::KeyRangeExtern,
asm::TotalControlFlow::Halt.into(),
];
vm.exec_ops(
ops,
*test_access(),
&state,
&|_: &Op| 1,
GasLimit::UNLIMITED,
)
.await
.unwrap();
assert_eq!(&vm.state_memory[..], &[vec![40], vec![41], vec![42]]);
assert_eq!(vm.state_memory.len(), 3);
}
#[tokio::test]
async fn state_read_ext_nones() {
let ext_contract_addr = ContentAddress([0x12; 32]);
let state = State::new(vec![(ext_contract_addr.clone(), vec![])]);
let mut vm = Vm::default();
let num_words = 3;
let [addr0, addr1, addr2, addr3] = word_4_from_u8_32(ext_contract_addr.0);
let ops = &[
asm::Stack::Push(num_words).into(),
asm::StateMemory::AllocSlots.into(),
asm::Stack::Push(addr0).into(),
asm::Stack::Push(addr1).into(),
asm::Stack::Push(addr2).into(),
asm::Stack::Push(addr3).into(),
asm::Stack::Push(1).into(), asm::Stack::Push(2).into(), asm::Stack::Push(3).into(), asm::Stack::Push(4).into(), asm::Stack::Push(4).into(), asm::Stack::Push(num_words).into(),
asm::Stack::Push(0).into(), asm::StateRead::KeyRangeExtern,
asm::TotalControlFlow::Halt.into(),
];
vm.exec_ops(
ops,
*test_access(),
&state,
&|_: &Op| 1,
GasLimit::UNLIMITED,
)
.await
.unwrap();
assert!(vm.state_memory.iter().all(Vec::is_empty));
assert_eq!(vm.state_memory.len(), 3);
}
#[tokio::test]
async fn state_read_various_size_values() {
let access = *test_access();
let state = State::new(vec![(
access
.solution
.this_data()
.predicate_to_solve
.contract
.clone(),
vec![
(vec![0, 0, 0, 0], vec![0; 2]),
(vec![0, 0, 0, 1], vec![1; 22]),
(vec![0, 0, 0, 2], vec![2; 14]),
(vec![0, 0, 0, 4], vec![4; 12]),
],
)]);
let mut vm = Vm::default();
let num_values = 5;
let ops = &[
asm::Stack::Push(num_values).into(),
asm::StateMemory::AllocSlots.into(),
asm::Stack::Push(0).into(), asm::Stack::Push(0).into(), asm::Stack::Push(0).into(), asm::Stack::Push(0).into(), asm::Stack::Push(4).into(), asm::Stack::Push(num_values).into(),
asm::Stack::Push(0).into(), asm::StateRead::KeyRange,
asm::TotalControlFlow::Halt.into(),
];
vm.exec_ops(ops, access, &state, &|_: &Op| 1, GasLimit::UNLIMITED)
.await
.unwrap();
assert_eq!(
&vm.state_memory[..],
&[vec![0; 2], vec![1; 22], vec![2; 14], vec![], vec![4; 12]]
);
assert_eq!(vm.state_memory.len(), 5);
}
#[tokio::test]
async fn state_read_various_key_sizes() {
let access = *test_access();
let state = State::new(vec![(
access
.solution
.this_data()
.predicate_to_solve
.contract
.clone(),
vec![
(vec![0], vec![0; 2]),
(vec![0, 1], vec![7; 6]),
(vec![1], vec![1; 22]),
(vec![0, 0, 0, 0, 0, 2], vec![2; 14]),
(vec![4; 1000], vec![4; 12]),
],
)]);
let mut vm = Vm::default();
let ops = &[
asm::Stack::Push(5).into(),
asm::StateMemory::AllocSlots.into(),
asm::Stack::Push(0).into(), asm::Stack::Push(1).into(), asm::Stack::Push(3).into(), asm::Stack::Push(0).into(), asm::StateRead::KeyRange,
asm::Stack::Push(0).into(),
asm::Stack::Push(0).into(),
asm::Stack::Push(0).into(),
asm::Stack::Push(0).into(),
asm::Stack::Push(0).into(),
asm::Stack::Push(2).into(),
asm::Stack::Push(6).into(), asm::Stack::Push(2).into(), asm::Stack::Push(3).into(), asm::StateRead::KeyRange,
asm::TotalControlFlow::Halt.into(),
];
vm.exec_ops(ops, access, &state, &|_: &Op| 1, GasLimit::UNLIMITED)
.await
.unwrap();
assert_eq!(
&vm.state_memory[..],
&[vec![0; 2], vec![1; 22], vec![], vec![2; 14], vec![]]
);
assert_eq!(vm.state_memory.len(), 5);
}
#[tokio::test]
async fn state_read_slot_index_overflow() {
let access = *test_access();
let state = State::new(vec![(
access
.solution
.this_data()
.predicate_to_solve
.contract
.clone(),
vec![(vec![0], vec![0; 2])],
)]);
let mut vm = Vm::default();
let ops = &[
asm::Stack::Push(1).into(),
asm::StateMemory::AllocSlots.into(),
asm::Stack::Push(0).into(), asm::Stack::Push(1).into(), asm::Stack::Push(1).into(), asm::Stack::Push(1).into(), asm::StateRead::KeyRange,
asm::TotalControlFlow::Halt.into(),
];
vm.exec_ops(ops, access, &state, &|_: &Op| 1, GasLimit::UNLIMITED)
.await
.unwrap_err();
}