use neo_devpack_solidity::runtime::execution::ExecutionContext;
use neo_devpack_solidity::runtime::RuntimeConfig;
use ripemd::Ripemd160;
use sha2::{Digest, Sha256};
fn syscall_id(name: &str) -> [u8; 4] {
let mut h = Sha256::new();
h.update(name.as_bytes());
let d = h.finalize();
[d[0], d[1], d[2], d[3]]
}
fn push_data(script: &mut Vec<u8>, data: &[u8]) {
assert!(
data.len() <= u8::MAX as usize,
"push_data only supports PUSHDATA1 lengths"
);
script.push(0x0C); script.push(data.len() as u8);
script.extend_from_slice(data);
}
const CRYPTOLIB_HASH_LE: [u8; 20] = [
0x1B, 0xF5, 0x75, 0xAB, 0x11, 0x89, 0x68, 0x84, 0x13, 0x61, 0x0A, 0x35, 0xA1, 0x28, 0x86, 0xCD,
0xE0, 0xB6, 0x6C, 0x72,
];
#[test]
fn hash160_matches_ripemd_sha256() {
let call_id = syscall_id("System.Contract.Call");
let mut code = vec![
0x57, 0x01, 0x00, ];
push_data(&mut code, b"data");
code.push(0x11); code.push(0xC0); code.push(0x1F); push_data(&mut code, b"sha256");
push_data(&mut code, &CRYPTOLIB_HASH_LE);
code.push(0x41); code.extend_from_slice(&call_id);
code.push(0x70);
code.push(0x68); code.push(0x11); code.push(0xC0); code.push(0x1F); push_data(&mut code, b"ripemd160");
push_data(&mut code, &CRYPTOLIB_HASH_LE);
code.push(0x41); code.extend_from_slice(&call_id);
code.push(0x40); let mut ctx = ExecutionContext::new(&RuntimeConfig::default()).expect("context init");
ctx.initialize(&code, &[]).expect("init");
while !ctx.step().expect("step").halted {}
let expected = Ripemd160::digest(Sha256::digest(b"data"));
assert_eq!(ctx.return_data(), expected.to_vec());
}
#[test]
fn hash256_double_sha256() {
let call_id = syscall_id("System.Contract.Call");
let mut code = vec![
0x57, 0x01, 0x00, ];
push_data(&mut code, b"abc");
code.push(0x11); code.push(0xC0); code.push(0x1F); push_data(&mut code, b"sha256");
push_data(&mut code, &CRYPTOLIB_HASH_LE);
code.push(0x41); code.extend_from_slice(&call_id);
code.push(0x70);
code.push(0x68); code.push(0x11); code.push(0xC0); code.push(0x1F); push_data(&mut code, b"sha256");
push_data(&mut code, &CRYPTOLIB_HASH_LE);
code.push(0x41); code.extend_from_slice(&call_id);
code.push(0x40); let mut ctx = ExecutionContext::new(&RuntimeConfig::default()).expect("context init");
ctx.initialize(&code, &[]).expect("init");
while !ctx.step().expect("step").halted {}
let expected = {
let first = Sha256::digest(b"abc");
Sha256::digest(first)
};
assert_eq!(ctx.return_data(), expected.to_vec());
}
#[test]
fn checksig_returns_boolean_result() {
let mut code = vec![0x0C, 0x21];
code.extend_from_slice(&[2u8; 33]);
code.extend_from_slice(&[0x0C, 0x46]);
code.extend_from_slice(&[0x30, 0x44, 0x02, 0x20]);
code.extend_from_slice(&[1u8; 32]); code.extend_from_slice(&[0x02, 0x20]);
code.extend_from_slice(&[2u8; 32]); code.extend_from_slice(&[0x41, 86, 231, 179, 39, 0x40]); let mut ctx = ExecutionContext::new(&RuntimeConfig::default()).expect("context init");
ctx.initialize(&code, &[]).expect("init");
while !ctx.step().expect("step").halted {}
assert!(ctx.return_data().len() == 1);
}