Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
573 changes: 284 additions & 289 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ bstr = "0.2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
hex = { version = "0.4.3", default-features = false }
near-sdk = { git = "https://github.com/near/near-sdk-rs", rev = "9d99077c6acfde68c06845f2a1eb2b5ed7983401" }
near-sdk-sim = { git = "https://github.com/near/near-sdk-rs", rev = "9d99077c6acfde68c06845f2a1eb2b5ed7983401" }
near-crypto = "0.1.0"
near-vm-runner = "4.0.0-pre.1"
near-vm-logic = "4.0.0-pre.1"
near-primitives-core = "0.4.0"
near-sdk = { git = "https://github.com/aurora-is-near/near-sdk-rs", rev = "1b9843fe5b652928582e33879fc92ba87a639450" }
near-sdk-sim = { git = "https://github.com/aurora-is-near/near-sdk-rs", rev = "1b9843fe5b652928582e33879fc92ba87a639450" }
near-crypto = { git = "https://github.com/near/nearcore.git", rev = "8a37d39629885a41dde58b60642bcf1e99407d90"}
near-vm-runner = { git = "https://github.com/near/nearcore.git", rev = "8a37d39629885a41dde58b60642bcf1e99407d90"}
near-vm-logic = { git = "https://github.com/near/nearcore.git", rev = "8a37d39629885a41dde58b60642bcf1e99407d90"}
near-primitives-core = { git = "https://github.com/near/nearcore.git", rev = "8a37d39629885a41dde58b60642bcf1e99407d90"}
libsecp256k1 = "0.3.5"
rand = "0.7.3"
criterion = "0.3.4"
Expand Down
16 changes: 13 additions & 3 deletions src/precompiles/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ pub struct RIPEMD160;

impl RIPEMD160 {
pub(super) const ADDRESS: Address = super::make_address(0, 3);

#[cfg(not(feature = "testnet"))]
fn internal_impl(input: &[u8]) -> [u8; 20] {
use ripemd160::Digest;
let hash = ripemd160::Ripemd160::digest(input);
let mut output = [0u8; 20];
output.copy_from_slice(&hash);
output
}
}

impl Precompile for RIPEMD160 {
Expand All @@ -106,13 +115,14 @@ impl Precompile for RIPEMD160 {
_context: &Context,
_is_static: bool,
) -> PrecompileResult {
use ripemd160::Digest;

let cost = Self::required_gas(input)?;
if cost > target_gas {
Err(ExitError::OutOfGas)
} else {
let hash = ripemd160::Ripemd160::digest(input);
#[cfg(not(feature = "testnet"))]
let hash = Self::internal_impl(input);
#[cfg(feature = "testnet")]
let hash = crate::sdk::ripemd160(input);
// The result needs to be padded with leading zeros because it is only 20 bytes, but
// the evm works with 32-byte words.
let mut output = vec![0u8; 32];
Expand Down
19 changes: 16 additions & 3 deletions src/precompiles/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,21 @@ mod consts {
/// See: https://etherscan.io/address/0000000000000000000000000000000000000001
// Quite a few library methods rely on this and that should be changed. This
// should only be for precompiles.
pub fn ecrecover(hash: H256, signature: &[u8]) -> Result<Address, ExitError> {
use sha3::Digest;
pub(crate) fn ecrecover(hash: H256, signature: &[u8]) -> Result<Address, ExitError> {
assert_eq!(signature.len(), 65);

#[cfg(feature = "testnet")]
return crate::sdk::ecrecover(hash, signature)
.map_err(|e| ExitError::Other(Borrowed(e.as_str())));

#[cfg(not(feature = "testnet"))]
internal_impl(hash, signature)
}

#[cfg(not(feature = "testnet"))]
fn internal_impl(hash: H256, signature: &[u8]) -> Result<Address, ExitError> {
use sha3::Digest;

let hash = secp256k1::Message::parse_slice(hash.as_bytes()).unwrap();
let v = signature[64];
let signature = secp256k1::Signature::parse_slice(&signature[0..64]).unwrap();
Expand All @@ -36,7 +47,9 @@ pub fn ecrecover(hash: H256, signature: &[u8]) -> Result<Address, ExitError> {
}
}

Err(ExitError::Other(Borrowed("invalid ECDSA signature")))
Err(ExitError::Other(Borrowed(
crate::sdk::ECRecoverErr.as_str(),
)))
}

pub(super) struct ECRecover;
Expand Down
73 changes: 73 additions & 0 deletions src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ use borsh::{BorshDeserialize, BorshSerialize};

const READ_STORAGE_REGISTER_ID: u64 = 0;
const INPUT_REGISTER_ID: u64 = 0;
#[cfg(feature = "testnet")]
const ECRECOVER_MESSAGE_SIZE: u64 = 32;
#[cfg(feature = "testnet")]
const ECRECOVER_SIGNATURE_LENGTH: u64 = 64;
#[cfg(feature = "testnet")]
const ECRECOVER_MALLEABILITY_FLAG: u64 = 1;

/// Register used to record evicted values from the storage.
const EVICTED_REGISTER: u64 = 0;
Expand Down Expand Up @@ -45,6 +51,16 @@ mod exports {
fn random_seed(register_id: u64);
pub(crate) fn sha256(value_len: u64, value_ptr: u64, register_id: u64);
pub(crate) fn keccak256(value_len: u64, value_ptr: u64, register_id: u64);
pub(crate) fn ripemd160(value_len: u64, value_ptr: u64, register_id: u64);
pub(crate) fn ecrecover(
hash_len: u64,
hash_ptr: u64,
sig_len: u64,
sig_ptr: u64,
v: u64,
malleability_flag: u64,
register_id: u64,
) -> u64;
// #####################
// # Miscellaneous API #
// #####################
Expand Down Expand Up @@ -372,6 +388,51 @@ pub fn keccak(input: &[u8]) -> H256 {
}
}

/// Calls environment ripemd160 on given input.
#[cfg(feature = "testnet")]
pub fn ripemd160(input: &[u8]) -> [u8; 20] {
unsafe {
const REGISTER_ID: u64 = 1;
exports::ripemd160(input.len() as u64, input.as_ptr() as u64, REGISTER_ID);
let bytes = [0u8; 20];
exports::read_register(REGISTER_ID, bytes.as_ptr() as u64);
bytes
}
}

/// Recover address from message hash and signature.
#[cfg(feature = "testnet")]
pub fn ecrecover(hash: H256, signature: &[u8]) -> Result<crate::prelude::Address, ECRecoverErr> {
unsafe {
let hash_ptr = hash.as_ptr() as u64;
let sig_ptr = signature.as_ptr() as u64;
const RECOVER_REGISTER_ID: u64 = 1;
const KECCACK_REGISTER_ID: u64 = 2;
let result = exports::ecrecover(
ECRECOVER_MESSAGE_SIZE,
hash_ptr,
ECRECOVER_SIGNATURE_LENGTH,
sig_ptr,
signature[64] as u64,
ECRECOVER_MALLEABILITY_FLAG,
RECOVER_REGISTER_ID,
);
if result == (true as u64) {
// The result from the ecrecover call is in a register; we can use this
// register directly for the input to keccak256. This is why the length is
// set to `u64::MAX`.
exports::keccak256(u64::MAX, RECOVER_REGISTER_ID, KECCACK_REGISTER_ID);
let keccak_hash_bytes = [0u8; 32];
exports::read_register(KECCACK_REGISTER_ID, keccak_hash_bytes.as_ptr() as u64);
Ok(crate::prelude::Address::from_slice(
&keccak_hash_bytes[12..],
))
} else {
Err(ECRecoverErr)
}
}
}

/// Returns account id of the current account.
pub fn current_account_id() -> Vec<u8> {
unsafe {
Expand Down Expand Up @@ -578,3 +639,15 @@ impl AsRef<[u8]> for ReadU64Error {
}
}
}

pub struct ECRecoverErr;
impl ECRecoverErr {
pub fn as_str(&self) -> &'static str {
"ERR_ECRECOVER"
}
}
impl AsRef<[u8]> for ECRecoverErr {
fn as_ref(&self) -> &[u8] {
self.as_str().as_bytes()
}
}
9 changes: 3 additions & 6 deletions src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ impl<'a> OneShotAuroraRunner<'a> {
);

near_vm_runner::run(
self.base.code.hash.as_ref().to_vec(),
&self.base.code.code.as_slice(),
&self.base.code,
method_name,
&mut self.ext,
self.context.clone(),
Expand Down Expand Up @@ -169,8 +168,7 @@ impl AuroraRunner {
);

let (maybe_outcome, maybe_error) = near_vm_runner::run(
self.code.hash.as_ref().to_vec(),
&self.code.code.as_slice(),
&self.code,
method_name,
&mut self.ext,
self.context.clone(),
Expand Down Expand Up @@ -277,8 +275,7 @@ impl AuroraRunner {
address.as_bytes().to_vec(),
);
let (outcome, maybe_error) = near_vm_runner::run(
self.code.hash.as_ref().to_vec(),
&self.code.code.as_slice(),
&self.code,
method_name,
&mut self.ext.clone(),
context,
Expand Down
Loading