fn emit_keccak256(
bytecode: &mut Vec<u8>,
use_callt: bool,
token_patches: &mut Vec<MethodTokenPatch>,
) {
emit_native_contract_call(
bytecode,
ir::NativeContract::CryptoLib,
"keccak256",
1,
use_callt,
token_patches,
)
}
fn emit_ecrecover(
bytecode: &mut Vec<u8>,
use_callt: bool,
token_patches: &mut Vec<MethodTokenPatch>,
) {
bytecode.push(0x8B); bytecode.push(0x50);
bytecode.push(0x4A); push_integer_bigint(bytecode, &BigInt::from(27u8));
bytecode.push(0xB5); let jmp_skip_add_pos = bytecode.len();
bytecode.push(0x27); let jmp_skip_add_operand = bytecode.len();
bytecode.extend_from_slice(&[0, 0, 0, 0]);
push_integer_bigint(bytecode, &BigInt::from(27u8));
bytecode.push(0x9E); let after_add_pos = bytecode.len();
let rel_after_add = (after_add_pos as i32)
.checked_sub(jmp_skip_add_pos as i32)
.unwrap_or(0);
bytecode[jmp_skip_add_operand..jmp_skip_add_operand + 4]
.copy_from_slice(&rel_after_add.to_le_bytes());
bytecode.push(0x11); bytecode.push(0x88); bytecode.push(0x4A); bytecode.push(0x51); bytecode.push(0x10); bytecode.push(0x50); bytecode.push(0xD0); bytecode.push(0x8B);
emit_native_contract_call(
bytecode,
ir::NativeContract::CryptoLib,
"recoverSecp256K1",
2,
use_callt,
token_patches,
);
bytecode.push(0x4A); bytecode.push(0xD8); let jmp_if_not_null_pos = bytecode.len();
bytecode.push(0x27); let jmp_if_not_null_operand = bytecode.len();
bytecode.extend_from_slice(&[0, 0, 0, 0]);
bytecode.push(0x45); push_data(bytecode, &[0u8; 20]);
let jmp_end_pos = bytecode.len();
bytecode.push(0x23); let jmp_end_operand = bytecode.len();
bytecode.extend_from_slice(&[0, 0, 0, 0]);
let not_null_pos = bytecode.len();
bytecode.push(0x4A); bytecode.push(0xCA); push_integer_bigint(bytecode, &BigInt::from(65u8));
bytecode.push(0xB5); let jmp_if_long_enough_pos = bytecode.len();
bytecode.push(0x27); let jmp_if_long_enough_operand = bytecode.len();
bytecode.extend_from_slice(&[0, 0, 0, 0]);
bytecode.push(0x45); push_data(bytecode, &[0u8; 20]);
let jmp_short_end_pos = bytecode.len();
bytecode.push(0x23); let jmp_short_end_operand = bytecode.len();
bytecode.extend_from_slice(&[0, 0, 0, 0]);
let long_enough_pos = bytecode.len();
push_integer_bigint(bytecode, &BigInt::from(1u8)); push_integer_bigint(bytecode, &BigInt::from(64u8)); bytecode.push(0x8C);
emit_native_contract_call(
bytecode,
ir::NativeContract::CryptoLib,
"keccak256",
1,
use_callt,
token_patches,
);
push_integer_bigint(bytecode, &BigInt::from(20u8));
bytecode.push(0x8E);
let end_pos = bytecode.len();
let rel_not_null = (not_null_pos as i32)
.checked_sub(jmp_if_not_null_pos as i32)
.unwrap_or(0);
bytecode[jmp_if_not_null_operand..jmp_if_not_null_operand + 4]
.copy_from_slice(&rel_not_null.to_le_bytes());
let rel_long_enough = (long_enough_pos as i32)
.checked_sub(jmp_if_long_enough_pos as i32)
.unwrap_or(0);
bytecode[jmp_if_long_enough_operand..jmp_if_long_enough_operand + 4]
.copy_from_slice(&rel_long_enough.to_le_bytes());
let rel_short_end = (end_pos as i32)
.checked_sub(jmp_short_end_pos as i32)
.unwrap_or(0);
bytecode[jmp_short_end_operand..jmp_short_end_operand + 4]
.copy_from_slice(&rel_short_end.to_le_bytes());
let rel_end = (end_pos as i32)
.checked_sub(jmp_end_pos as i32)
.unwrap_or(0);
bytecode[jmp_end_operand..jmp_end_operand + 4].copy_from_slice(&rel_end.to_le_bytes());
}
fn emit_verify_signature(
bytecode: &mut Vec<u8>,
use_callt: bool,
token_patches: &mut Vec<MethodTokenPatch>,
) {
push_integer_bigint(bytecode, &BigInt::from(23u8)); emit_native_contract_call(
bytecode,
ir::NativeContract::CryptoLib,
"verifyWithECDsa",
4,
use_callt,
token_patches,
);
}
fn emit_precompile_ecrecover(
bytecode: &mut Vec<u8>,
use_callt: bool,
token_patches: &mut Vec<MethodTokenPatch>,
) {
bytecode.push(0x4A); bytecode.push(0xCA); push_integer_bigint(bytecode, &BigInt::from(128u8));
bytecode.push(0xB5); let jmp_payload_long_enough_pos = bytecode.len();
bytecode.push(0x27); let jmp_payload_long_enough_operand = bytecode.len();
bytecode.extend_from_slice(&[0, 0, 0, 0]);
bytecode.push(0x45); push_data(bytecode, &[0u8; 32]);
let jmp_payload_end_pos = bytecode.len();
bytecode.push(0x23); let jmp_payload_end_operand = bytecode.len();
bytecode.extend_from_slice(&[0, 0, 0, 0]);
let payload_long_enough_pos = bytecode.len();
bytecode.push(0x4A); push_integer_bigint(bytecode, &BigInt::from(0u8));
push_integer_bigint(bytecode, &BigInt::from(32u8));
bytecode.push(0x8C); bytecode.push(0x50);
bytecode.push(0x4A); push_integer_bigint(bytecode, &BigInt::from(32u8));
push_integer_bigint(bytecode, &BigInt::from(32u8));
bytecode.push(0x8C); push_integer_bigint(bytecode, &BigInt::from(1u8));
bytecode.push(0x8E); bytecode.push(0xDB); bytecode.push(0x21); bytecode.push(0x50);
bytecode.push(0x4A); push_integer_bigint(bytecode, &BigInt::from(64u8));
push_integer_bigint(bytecode, &BigInt::from(32u8));
bytecode.push(0x8C); bytecode.push(0x50);
push_integer_bigint(bytecode, &BigInt::from(96u8));
push_integer_bigint(bytecode, &BigInt::from(32u8));
bytecode.push(0x8C);
emit_ecrecover(bytecode, use_callt, token_patches);
push_data(bytecode, &[0u8; 12]);
bytecode.push(0x50); bytecode.push(0x8B);
let payload_end_pos = bytecode.len();
let rel_payload_long_enough = (payload_long_enough_pos as i32)
.checked_sub(jmp_payload_long_enough_pos as i32)
.unwrap_or(0);
bytecode[jmp_payload_long_enough_operand..jmp_payload_long_enough_operand + 4]
.copy_from_slice(&rel_payload_long_enough.to_le_bytes());
let rel_payload_end = (payload_end_pos as i32)
.checked_sub(jmp_payload_end_pos as i32)
.unwrap_or(0);
bytecode[jmp_payload_end_operand..jmp_payload_end_operand + 4]
.copy_from_slice(&rel_payload_end.to_le_bytes());
}
fn emit_precompile_modexp(bytecode: &mut Vec<u8>, _use_callt: bool) {
for &len_byte_offset in &[31u8, 63u8, 95u8] {
bytecode.push(0x4A); push_integer_bigint(bytecode, &BigInt::from(len_byte_offset));
push_integer_bigint(bytecode, &BigInt::from(1u8));
bytecode.push(0x8C); bytecode.push(0xDB); bytecode.push(0x21); push_integer_bigint(bytecode, &BigInt::from(1u8));
bytecode.push(0xB3); bytecode.push(0x39); }
bytecode.push(0x4A); push_integer_bigint(bytecode, &BigInt::from(96u8));
push_integer_bigint(bytecode, &BigInt::from(1u8));
bytecode.push(0x8C); bytecode.push(0xDB); bytecode.push(0x21); bytecode.push(0x50);
bytecode.push(0x4A); push_integer_bigint(bytecode, &BigInt::from(97u8));
push_integer_bigint(bytecode, &BigInt::from(1u8));
bytecode.push(0x8C); bytecode.push(0xDB); bytecode.push(0x21); bytecode.push(0x50);
push_integer_bigint(bytecode, &BigInt::from(98u8));
push_integer_bigint(bytecode, &BigInt::from(1u8));
bytecode.push(0x8C); bytecode.push(0xDB); bytecode.push(0x21);
bytecode.push(0xA6);
bytecode.push(0xDB); bytecode.push(0x28); push_data(bytecode, &[0u8; 32]);
bytecode.push(0x50); bytecode.push(0x8B); bytecode.push(0x4A); bytecode.push(0xCA); push_integer_bigint(bytecode, &BigInt::from(32u8));
bytecode.push(0x9F); push_integer_bigint(bytecode, &BigInt::from(32u8));
bytecode.push(0x8C); }