diff --git a/crates/evm/lib.rs b/crates/evm/lib.rs index a69a6142..c50c0c7d 100644 --- a/crates/evm/lib.rs +++ b/crates/evm/lib.rs @@ -1,3 +1,4 @@ +pub use primitive_types::H128; pub use primitive_types::U256; use tiny_keccak::Hasher; use tiny_keccak::Keccak; @@ -35,6 +36,42 @@ fn to_signed(value: U256) -> U256 { } } +fn get_window_data( + data: &Vec, + window_size: usize, + offset: usize, +) -> Vec { + let start_index = offset % data.len(); + let end_index = start_index + window_size; + + // Ensure the end index doesn't go beyond the length of the data + let end_index = if end_index > data.len() { + data.len() + } else { + end_index + }; + + // Return the data within the specified window + data[start_index..end_index].to_vec() +} + +fn filter_left_zeros(data: Vec) -> Vec { + let mut result = Vec::new(); + let mut found_non_zero = false; + + for &value in &data { + if value > 0 { + found_non_zero = true; + } + + if found_non_zero || value > 0 { + result.push(value); + } + } + + result +} + repr_u8! { // EVM instructions #[repr(u8)] @@ -222,6 +259,10 @@ impl Stack { self.data[self.data.len() - 1] } + pub fn peek_step(&self, step: usize) -> U256 { + self.data[self.data.len() - step] + } + pub fn swap(&mut self, index: usize) { let ptr = self.data.len() - 1; @@ -338,6 +379,8 @@ impl<'a> Machine<'a> { ) -> ExecutionState { let mut pc = 0; let len = bytecode.len(); + let mut counter = 0; + while pc < len { let opcode = bytecode[pc]; let inst = match Instruction::try_from(opcode) { @@ -350,34 +393,58 @@ impl<'a> Machine<'a> { let cost = (self.cost_fn)(&inst); pc += 1; + counter += 1; + + if counter == 400 { + break; + } - //println!("STACK: {:?}", self.stack); + println!("{:#?}", inst); + println!("OPCODE: {:#?}", opcode); + + println!("Position: {:#?}", pc - 1); + println!("Counter: {:#?}", counter); + + println!("==================="); match inst { Instruction::Stop => {} Instruction::Add => { let lhs = self.stack.pop(); let rhs = self.stack.pop(); - self.stack.push(lhs + rhs); + let lhs16: u16 = lhs.as_u64() as u16; + let rhs16: u16 = rhs.as_u64() as u16; + let sum = U256::from(lhs16.overflowing_add(rhs16).0); + self.stack.push(sum); } Instruction::Sub => { let lhs = self.stack.pop(); let rhs = self.stack.pop(); - self.stack.push(lhs - rhs); + + let lhs16: u16 = lhs.as_u64() as u16; // culprits causing an issue + let rhs16: u16 = rhs.as_u64() as u16; // Should wallet be converted to base16? We need to see what obj truth offers wallet conversion + + let difference = U256::from(lhs16.overflowing_sub(rhs16).0); + self.stack.push(difference); } Instruction::Mul => { let lhs = self.stack.pop(); let rhs = self.stack.pop(); - self.stack.push(lhs * rhs); + let lhs16: u16 = lhs.as_u64() as u16; + let rhs16: u16 = rhs.as_u64() as u16; + let product = U256::from(lhs16.overflowing_mul(rhs16).0); + self.stack.push(product); } Instruction::Div => { let lhs = self.stack.pop(); let rhs = self.stack.pop(); - + let lhs16: u16 = lhs.as_u64() as u16; + let rhs16: u16 = rhs.as_u64() as u16; + let quotient = U256::from(lhs16.overflowing_div(rhs16).0); if rhs == U256::zero() { return ExecutionState::Abort(AbortError::DivZero); } - self.stack.push(lhs / rhs); + self.stack.push(quotient); } Instruction::SDiv => { let dividend = to_signed(self.stack.pop()); @@ -556,6 +623,18 @@ impl<'a> Machine<'a> { self.stack.push(U256::zero()); } } + + Instruction::Shl => { + let rhs = self.stack.pop(); + let lhs = self.stack.pop(); + + if rhs < U256::from(256) { + self.stack.push(lhs << rhs); + } else { + self.stack.push(U256::zero()); + } + } + Instruction::Eq => { let lhs = self.stack.pop(); let rhs = self.stack.pop(); @@ -595,8 +674,9 @@ impl<'a> Machine<'a> { } Instruction::Not => { let val = self.stack.pop(); - - self.stack.push(!val); + let val16: u16 = val.as_u64() as u16; + let not_val16 = U256::from(!val16); + self.stack.push(not_val16); } Instruction::Byte => { let rhs = self.stack.pop(); @@ -686,7 +766,6 @@ impl<'a> Machine<'a> { self.stack.push(U256::from(len)); } Instruction::CodeCopy => { - // NOTE about codecopy: We need to determine what sets initial memory size & thru out init & runtime bytecode let mem_offset = self.stack.pop().low_u64() as usize; let code_offset = self.stack.pop(); let len = self.stack.pop().low_u64() as usize; @@ -695,30 +774,26 @@ impl<'a> Machine<'a> { } let code_offset = code_offset.low_u64() as usize; - //if code_offset < self.data.len() { - let code = &bytecode[code_offset..code_offset + len]; - //ATTENTION: Later investigate if code is being injected into memory correctly - // I dont think the below code is correct. - if self.memory.len() < mem_offset + 32 { - self.memory.resize(mem_offset + 32, 0); + let code: &[u8]; + // Needed for testing parts of bytecode to avoid out of bound errors in &bytecode[code_offset..code_offset + len] + let mut temp_vec: Vec = vec![]; + //println!("mem_offset: {:#?}", mem_offset); + //println!("code_offset: {:#?}", code_offset); + //println!("len: {:#?}", len); + //println!("Memory Size: {:#?}", self.memory.len()); + + if self.memory.len() < (mem_offset + len) { + self.memory.extend( + std::iter::repeat(0).take(mem_offset + len - self.memory.len()), + ); } + code = &bytecode[code_offset..code_offset + len]; + //println!("Grabbed Code: {:#?}", code); - // Calculate padding for resizing - let current_size = code.len() + mem_offset; - let remainder = current_size % 32; - let padding = if remainder == 0 { 0 } else { 32 - remainder }; - - // Resize - self.memory.resize(current_size + padding + 32, 0); //Calculate new space of zeroes for i in 0..=code.len() - 1 { - if i > code.len() { - self.memory[mem_offset + i] = 0; - } else { - self.memory[mem_offset + i] = code[i]; - } + self.memory[mem_offset + i] = code[i]; } - //} } Instruction::ExtCodeSize => { // Fetch the `Contract-Src` from Arweave for the contract. @@ -775,14 +850,38 @@ impl<'a> Machine<'a> { if offset > usize::max_value().into() { dbg!("MLOAD: offset too large"); } + let len = offset.low_u64() as usize; - let mut data = vec![0u8; 32]; - for (idx, mem_ptr) in (0..len).zip(len..len + 32) { - data[idx] = self.memory[mem_ptr]; + // Calcuate bytes to add to memory based on offset + let num_memory_rows = self.memory.len() / 32; + let offset_needed_rows = ((len + 32) as f64 / 32.0).ceil() as usize; + //println!("OFFSET: {:#?}", len); + //println!("num_memory_rows: {:#?}", num_memory_rows); + //println!("offset_needed_row {:#?}", offset_needed_rows); + + let rows_to_add = offset_needed_rows as i32 - num_memory_rows as i32; + //println!("rows_to_add {:#?}", rows_to_add); + + if rows_to_add > 0 { + for _ in 0..=rows_to_add - 1 { + self.memory.extend(std::iter::repeat(0).take(32)); + } } - self.stack.push(U256::from(data.as_slice())); + let word = get_window_data(&self.memory, 32, len); + let filtered_word = filter_left_zeros(word); + let filtered_hex: Vec = filtered_word + .iter() + .map(|u256| format!("{:02x}", u256)) + .collect(); + let joined_filtered: String = filtered_hex + .into_iter() + .map(|byte| byte.to_string()) + .collect(); + let word_u256 = + U256::from_str_radix(joined_filtered.as_str(), 16).unwrap(); + self.stack.push(U256::from(word_u256)); } Instruction::MStore => { let offset = self.stack.pop(); @@ -885,6 +984,7 @@ impl<'a> Machine<'a> { | Instruction::Push32 => { let value_size = (opcode - 0x60 + 1) as usize; let value = &bytecode[pc..pc + value_size]; + println!("VALUE ADDED {:#?} :", value); pc += value_size; self.stack.push(U256::from(value)); } @@ -1305,17 +1405,24 @@ mod tests { */ #[test] fn test_erc_constructor() { - //60015f60026003 - let bytes = hex!("608060405234801561000f575f80fd5b5060405161015a38038061015a83398181016040528101906100319190610074565b805f819055505061009f565b5f80fd5b5f819050919050565b61005381610041565b811461005d575f80fd5b50565b5f8151905061006e8161004a565b92915050565b5f602082840312156100895761008861003d565b5b5f61009684828501610060565b91505092915050565b60af806100ab5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063eea32eb214602a575b5f80fd5b60306044565b604051603b91906062565b60405180910390f35b5f8054905090565b5f819050919050565b605c81604c565b82525050565b5f60208201905060735f8301846055565b9291505056fea2646970667358221220e172226e595342e8a3f2ef9078c5da77614a34292db622e83940893b7979708764736f6c634300081400330000000000000000000000000000000000000000000000000000000000000003"); + let bytes = hex!("608060405234801562000010575f80fd5b506040516200166f3803806200166f8339818101604052810190620000369190620003cb565b6040518060400160405280600481526020017f476f6c64000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f474c4400000000000000000000000000000000000000000000000000000000008152508160039081620000b3919062000656565b508060049081620000c5919062000656565b505050620000da3382620000e160201b60201c565b5062000866565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000154575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016200014b91906200077d565b60405180910390fd5b620001675f83836200016b60201b60201c565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603620001bf578060025f828254620001b29190620007c5565b9250508190555062000290565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156200024b578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401620002429392919062000810565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620002d9578060025f828254039250508190555062000323565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516200038291906200084b565b60405180910390a3505050565b5f80fd5b5f819050919050565b620003a78162000393565b8114620003b2575f80fd5b50565b5f81519050620003c5816200039c565b92915050565b5f60208284031215620003e357620003e26200038f565b5b5f620003f284828501620003b5565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200047757607f821691505b6020821081036200048d576200048c62000432565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620004f17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620004b4565b620004fd8683620004b4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6200053e62000538620005328462000393565b62000515565b62000393565b9050919050565b5f819050919050565b62000559836200051e565b62000571620005688262000545565b848454620004c0565b825550505050565b5f90565b6200058762000579565b620005948184846200054e565b505050565b5b81811015620005bb57620005af5f826200057d565b6001810190506200059a565b5050565b601f8211156200060a57620005d48162000493565b620005df84620004a5565b81016020851015620005ef578190505b62000607620005fe85620004a5565b83018262000599565b50505b505050565b5f82821c905092915050565b5f6200062c5f19846008026200060f565b1980831691505092915050565b5f6200064683836200061b565b9150826002028217905092915050565b6200066182620003fb565b67ffffffffffffffff8111156200067d576200067c62000405565b5b6200068982546200045f565b62000696828285620005bf565b5f60209050601f831160018114620006cc575f8415620006b7578287015190505b620006c3858262000639565b86555062000732565b601f198416620006dc8662000493565b5f5b828110156200070557848901518255600182019150602085019450602081019050620006de565b8683101562000725578489015162000721601f8916826200061b565b8355505b6001600288020188555050505b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f62000765826200073a565b9050919050565b620007778162000759565b82525050565b5f602082019050620007925f8301846200076c565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f620007d18262000393565b9150620007de8362000393565b9250828201905080821115620007f957620007f862000798565b5b92915050565b6200080a8162000393565b82525050565b5f606082019050620008255f8301866200076c565b620008346020830185620007ff565b620008436040830184620007ff565b949350505050565b5f602082019050620008605f830184620007ff565b92915050565b610dfb80620008745f395ff3fe608060405234801561000f575f80fd5b5060043610610091575f3560e01c8063313ce56711610064578063313ce5671461013157806370a082311461014f57806395d89b411461017f578063a9059cbb1461019d578063dd62ed3e146101cd57610091565b806306fdde0314610095578063095ea7b3146100b357806318160ddd146100e357806323b872dd14610101575b5f80fd5b61009d6101fd565b6040516100aa9190610a74565b60405180910390f35b6100cd60048036038101906100c89190610b25565b61028d565b6040516100da9190610b7d565b60405180910390f35b6100eb6102af565b6040516100f89190610ba5565b60405180910390f35b61011b60048036038101906101169190610bbe565b6102b8565b6040516101289190610b7d565b60405180910390f35b6101396102e6565b6040516101469190610c29565b60405180910390f35b61016960048036038101906101649190610c42565b6102ee565b6040516101769190610ba5565b60405180910390f35b610187610333565b6040516101949190610a74565b60405180910390f35b6101b760048036038101906101b29190610b25565b6103c3565b6040516101c49190610b7d565b60405180910390f35b6101e760048036038101906101e29190610c6d565b6103e5565b6040516101f49190610ba5565b60405180910390f35b60606003805461020c90610cd8565b80601f016020809104026020016040519081016040528092919081815260200182805461023890610cd8565b80156102835780601f1061025a57610100808354040283529160200191610283565b820191905f5260205f20905b81548152906001019060200180831161026657829003601f168201915b5050505050905090565b5f80610297610467565b90506102a481858561046e565b600191505092915050565b5f600254905090565b5f806102c2610467565b90506102cf858285610480565b6102da858585610512565b60019150509392505050565b5f6012905090565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b60606004805461034290610cd8565b80601f016020809104026020016040519081016040528092919081815260200182805461036e90610cd8565b80156103b95780601f10610390576101008083540402835291602001916103b9565b820191905f5260205f20905b81548152906001019060200180831161039c57829003601f168201915b5050505050905090565b5f806103cd610467565b90506103da818585610512565b600191505092915050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f33905090565b61047b8383836001610602565b505050565b5f61048b84846103e5565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461050c57818110156104fd578281836040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526004016104f493929190610d17565b60405180910390fd5b61050b84848484035f610602565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610582575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016105799190610d4c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036105f2575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016105e99190610d4c565b60405180910390fd5b6105fd8383836107d1565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610672575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016106699190610d4c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106e2575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016106d99190610d4c565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555080156107cb578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516107c29190610ba5565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610821578060025f8282546108159190610d92565b925050819055506108ef565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156108aa578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016108a193929190610d17565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610936578060025f8282540392505081905550610980565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516109dd9190610ba5565b60405180910390a3505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610a21578082015181840152602081019050610a06565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610a46826109ea565b610a5081856109f4565b9350610a60818560208601610a04565b610a6981610a2c565b840191505092915050565b5f6020820190508181035f830152610a8c8184610a3c565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610ac182610a98565b9050919050565b610ad181610ab7565b8114610adb575f80fd5b50565b5f81359050610aec81610ac8565b92915050565b5f819050919050565b610b0481610af2565b8114610b0e575f80fd5b50565b5f81359050610b1f81610afb565b92915050565b5f8060408385031215610b3b57610b3a610a94565b5b5f610b4885828601610ade565b9250506020610b5985828601610b11565b9150509250929050565b5f8115159050919050565b610b7781610b63565b82525050565b5f602082019050610b905f830184610b6e565b92915050565b610b9f81610af2565b82525050565b5f602082019050610bb85f830184610b96565b92915050565b5f805f60608486031215610bd557610bd4610a94565b5b5f610be286828701610ade565b9350506020610bf386828701610ade565b9250506040610c0486828701610b11565b9150509250925092565b5f60ff82169050919050565b610c2381610c0e565b82525050565b5f602082019050610c3c5f830184610c1a565b92915050565b5f60208284031215610c5757610c56610a94565b5b5f610c6484828501610ade565b91505092915050565b5f8060408385031215610c8357610c82610a94565b5b5f610c9085828601610ade565b9250506020610ca185828601610ade565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610cef57607f821691505b602082108103610d0257610d01610cab565b5b50919050565b610d1181610ab7565b82525050565b5f606082019050610d2a5f830186610d08565b610d376020830185610b96565b610d446040830184610b96565b949350505050565b5f602082019050610d5f5f830184610d08565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610d9c82610af2565b9150610da783610af2565b9250828201905080821115610dbf57610dbe610d65565b5b9291505056fea26469706673582212209e44fcf9f1633c4ef31f016a68dcf977b7606fd376618fb0b59f05773c82a5f864736f6c63430008160033000000000000000000000000000000000000000000000000000000000000007b"); + //let bytes = hex!("7f476f6c6400000000000000000000000000000000000000000000000000000000"); let mut machine = Machine::new(test_cost_fn); let status = machine.execute(&bytes, Default::default()); //assert_eq!(status, ExecutionState::Ok); - println!("LOOK DOWN"); - println!("Result: {:#?}", machine.result); + println!("EVM INFO"); + //println!("Result: {:#?}", machine.result); println!("Storage: {:#?}", machine.storage); println!("Memory: {:#?}", machine.memory); println!("Stack: {:#?}", machine.stack); + + /* + let test_wallet = U256::from("be862ad9abfe6f22bcb087716c7d89a26051f74b"); + let convert_wallet: u16 = test_wallet.as_u64() as u16; + println!("Wallet to u256 {:#?}", test_wallet); + println!("Wallet to u16 {:#?}", convert_wallet); + */ } /* #[test] @@ -1364,3 +1471,15 @@ mod tests { } */ } +/* +Yield integer overflow error to u64 +60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01 +*/ + +/* +476f6c6400000000000000000000000000000000000000000000000000000000 is the PUSH32 (7F) value + +result in decimal: + +40343534588991024208220822200420820688602844086 +*/ diff --git a/crates/exm/base.js b/crates/exm/base.js index 946c2ff9..9a75cc4c 100644 --- a/crates/exm/base.js +++ b/crates/exm/base.js @@ -238,7 +238,6 @@ testDelKv() { return this.kv; } - async sha256(buffer) { return subtle.digest('SHA-256', buffer).then((hashBuffer) => { const hashArray = Array.from(new Uint8Array(hashBuffer)); @@ -248,7 +247,6 @@ return hashHex; }); } - } const ExmSymbol = Symbol('exm'); diff --git a/crates/smartweave/smartweave.js b/crates/smartweave/smartweave.js index 1e3870a4..6151d413 100644 --- a/crates/smartweave/smartweave.js +++ b/crates/smartweave/smartweave.js @@ -367,6 +367,21 @@ }; } + get convertString() { + return { + async toSHA256(input) { + const encoder = new TextEncoder(); + const data = encoder.encode(input); + const hashBuffer = await globalThis.SmartWeave.arweave.crypto.hash(data); + const hashArray = Array.from(hashBuffer); + const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join(''); + + return hashHex; + + } + } + } + get unsafeClient() { const txGetData = async (txId, opts) => { try { diff --git a/docs/opcodes.md b/docs/opcodes.md new file mode 100644 index 00000000..b7d96e5d --- /dev/null +++ b/docs/opcodes.md @@ -0,0 +1,50 @@ + +## List of the supported and tested 3EM EVM opcodes: + +| opcodes | status | +|:---------:|:--------:| +| `CallValue` | ✅ | +| `Dup1` | ✅ | +| `IsZero` | ✅ | +| `Push3` | ✅ | +| `JumpI` | ✅ | +| `JumpDest` | ✅ | +| `Pop` | ✅ | +| `Push1` | ✅ | +| `MLoad` | ✅ | +| `CodeSize` | ✅ | +| `Sub` | ✅ | +| `CodeCopy` | ✅ | +| `Dup2` | ✅ | +| `Add` | ✅ | +| `MStore` | ✅ | +| `Swap1` | ✅ | +| `Swap2` | ✅ | +| `Jump` | ✅ | +| `Push0` | ✅ | +| `Dup3` | ✅ | +| `Dup5` | ✅ | +| `SLt` | ✅ | +| `Dup6` | ✅ | +| `Eq` | ✅ | +| `Swap3` | ✅ | +| `Push32` | ✅ | +| `Push8` | ✅ | +| `Gt` | ✅ | +| `SLoad` | ✅ | +| `Div` | ✅ | +| `And` | ✅ | +| `Lt` | ✅ | +| `Dup4` | ✅ | +| `Dup8` | ✅ | +| `Not` | ✅ | +| `Mul` | ✅ | +| `Shr` | ✅ | +| `Or` | ✅ | +| `Dup7` | ✅ | +| `SStore` | ✅ | +| `Caller` | ✅ | +| `Shl` | ✅ | +| `Push20` | ✅ | +| `Revert` | ✅ | +| `Mload` | ✅ | diff --git a/js/napi/src/lib.rs b/js/napi/src/lib.rs index 96c9f2d9..822ff84b 100644 --- a/js/napi/src/lib.rs +++ b/js/napi/src/lib.rs @@ -554,6 +554,7 @@ mod tests { let contract_result = contract.state; let str_state = contract_result.to_string(); + //println!("STATUS::::: {:#?}", str_state.contains("wearemintingyes")); assert!(str_state.contains("wearemintingyes")); } @@ -753,16 +754,52 @@ mod tests { }; let contract = simulate_contract(execution_context).await.unwrap(); - //println!("{}", contract.exm_context); - //println!("{}", contract.result); assert_eq!(contract.result, "[\"Yangtze\",\"Amazon\"]"); } - + + #[tokio::test] + pub async fn simulate_sha256() { + let contract_source_bytes = + include_bytes!("../../../testdata/contracts/sha256.js"); + let contract_source_vec = contract_source_bytes.to_vec(); + let execution_context: SimulateExecutionContext = + SimulateExecutionContext { + contract_id: String::new(), + interactions: vec![SimulateInput { + id: String::from("abcd"), + owner: String::from("210392sdaspd-asdm-asd_sa0d1293-lc"), + quantity: String::from("12301"), + reward: String::from("12931293"), + target: None, + tags: vec![], + block: None, + input: serde_json::json!({ + "act": "1", + }) + .to_string(), + }], + contract_init_state: Some(r#"{}"#.into()), + maybe_config: None, + maybe_cache: Some(false), + maybe_bundled_contract: None, + maybe_settings: None, + maybe_exm_context: Some(r#"{"requests": {}, "kv": {}, "initiated":[]}"#.into()), + maybe_contract_source: Some(ContractSource { + contract_src: contract_source_vec.into(), + contract_type: SimulateContractType::JAVASCRIPT, + }), + }; + + let contract = simulate_contract(execution_context).await.unwrap(); + const hello_hash: &str = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"; + assert_eq!(contract.state[0], hello_hash); + } + #[tokio::test] pub async fn simulate_kv_get() { let contract_source_bytes = include_bytes!("../../../testdata/contracts/getKv.js"); - + let contract_source_vec = contract_source_bytes.to_vec(); let execution_context: SimulateExecutionContext = SimulateExecutionContext { diff --git a/testdata/contracts/sha256.js b/testdata/contracts/sha256.js new file mode 100644 index 00000000..a252277e --- /dev/null +++ b/testdata/contracts/sha256.js @@ -0,0 +1,8 @@ +export async function handle(state, action) { + try { + const someSha = await SmartWeave.convertString.toSHA256("hello"); + return { state: [someSha] }; + } catch(e) { + return { state: e.toString() } + } +}