Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: access key mgmt for relayer #678

Closed
wants to merge 1 commit into from
Closed
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
40 changes: 40 additions & 0 deletions .taplo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[formatting]
# Align consecutive entries vertically.
align_entries = false

# Append trailing commas for multi-line arrays.
array_trailing_comma = true

# Expand arrays to multiple lines that exceed the maximum column width.
array_auto_expand = false

# Collapse arrays that don't exceed the maximum column width and don't contain comments.
array_auto_collapse = true

# Omit white space padding from single-line arrays
compact_arrays = true

# Omit white space padding from the start and end of inline tables.
compact_inline_tables = false

# Maximum column width in characters, affects array expansion and collapse, this doesn't take whitespace into account.
# Note that this is not set in stone, and works on a best-effort basis.
column_width = 80

# Indent based on tables and arrays of tables and their subtables, subtables out of order are not indented.
indent_tables = true

# The substring that is used for indentation, should be tabs or spaces (but technically can be anything).
indent_string = ' '

# Add trailing newline at the end of the file if not present.
trailing_newline = true

# Alphabetically reorder keys that are not separated by empty lines.
reorder_keys = false

# Maximum amount of allowed consecutive blank lines. This does not affect the whitespace at the end of the document, as it is always stripped.
allowed_blank_lines = 2

# Use CRLF for line endings.
crlf = false
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 9 additions & 11 deletions engine-sdk/src/near_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ impl crate::promise::PromiseHandler for Runtime {
receiver_id,
function_names,
} => {
feature_gated!("all-promise-actions", {
{
let pk: RawPublicKey = public_key.into();
let pk_bytes = pk.as_bytes();
let allowance = allowance.as_u128();
Expand All @@ -432,18 +432,16 @@ impl crate::promise::PromiseHandler for Runtime {
function_names.len() as _,
function_names.as_ptr() as _,
)
});
};
}
PromiseAction::DeleteKey { public_key } => {
feature_gated!("all-promise-actions", {
let pk: RawPublicKey = public_key.into();
let pk_bytes = pk.as_bytes();
exports::promise_batch_action_delete_key(
id,
pk_bytes.len() as _,
pk_bytes.as_ptr() as _,
)
});
let pk: RawPublicKey = public_key.into();
let pk_bytes = pk.as_bytes();
exports::promise_batch_action_delete_key(
id,
pk_bytes.len() as _,
pk_bytes.as_ptr() as _,
)
}
PromiseAction::DeleteAccount { beneficiary_id } => {
feature_gated!("all-promise-actions", {
Expand Down
22 changes: 22 additions & 0 deletions engine-tests/src/test_utils/asserts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use near_primitives::transaction::ExecutionStatus;

pub fn assert_execution_status_failure(
execution_status: ExecutionStatus,
err_msg: &str,
panic_msg: &str,
) {
// Usually the converted to string has either of following two messages formats:
// "Action #0: Smart contract panicked: ERR_MSG [src/some_file.rs:LINE_NUMBER:COLUMN_NUMBER]"
// "right: 'MISMATCHED_DATA': ERR_MSG [src/some_file.rs:LINE_NUMBER:COLUMN_NUMBER]"
// So the ": ERR_MSG [" pattern should catch all invariants of error, even if one of the errors
// message is a subset of another one (e.g. `ERR_MSG_FAILED` is a subset of `ERR_MSG_FAILED_FOO`)
let expected_err_msg_pattern = format!(": {}", err_msg);

match execution_status {
ExecutionStatus::Failure(err) => {
println!("Error: {}", err);
assert!(err.to_string().contains(&expected_err_msg_pattern));
}
_ => panic!("{}", panic_msg),
}
}
1 change: 1 addition & 0 deletions engine-tests/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub(crate) const PAUSE_PRECOMPILES: &str = "pause_precompiles";
pub(crate) const PAUSED_PRECOMPILES: &str = "paused_precompiles";
pub(crate) const RESUME_PRECOMPILES: &str = "resume_precompiles";

pub(crate) mod asserts;
pub(crate) mod erc20;
pub(crate) mod exit_precompile;
pub(crate) mod mocked_external;
Expand Down
22 changes: 1 addition & 21 deletions engine-tests/src/tests/eth_connector.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::prelude::Address;
use crate::prelude::WithdrawCallArgs;
use crate::test_utils::asserts::assert_execution_status_failure;
use crate::test_utils::str_to_account_id;
use aurora_engine::admin_controlled::{PausedMask, ERR_PAUSED};
use aurora_engine::connector::{
Expand Down Expand Up @@ -1547,27 +1548,6 @@ fn test_deposit_to_aurora_amount_equal_fee_non_zero() {
assert_proof_was_not_used(&contract, CONTRACT_ACC, proof_str);
}

fn assert_execution_status_failure(
execution_status: ExecutionStatus,
err_msg: &str,
panic_msg: &str,
) {
// Usually the converted to string has either of following two messages formats:
// "Action #0: Smart contract panicked: ERR_MSG [src/some_file.rs:LINE_NUMBER:COLUMN_NUMBER]"
// "right: 'MISMATCHED_DATA': ERR_MSG [src/some_file.rs:LINE_NUMBER:COLUMN_NUMBER]"
// So the ": ERR_MSG [" pattern should catch all invariants of error, even if one of the errors
// message is a subset of another one (e.g. `ERR_MSG_FAILED` is a subset of `ERR_MSG_FAILED_FOO`)
let expected_err_msg_pattern = format!(": {}", err_msg);

match execution_status {
ExecutionStatus::Failure(err) => {
println!("Error: {}", err);
assert!(err.to_string().contains(&expected_err_msg_pattern));
}
_ => panic!("{}", panic_msg),
}
}

#[test]
fn test_ft_transfer_max_value() {
let (_, contract) = init(CUSTODIAN_ADDRESS);
Expand Down
1 change: 1 addition & 0 deletions engine-tests/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod pausable_precompiles;
mod prepaid_gas_precompile;
mod promise_results_precompile;
mod random;
mod relayer_keys;
mod repro;
pub(crate) mod sanity;
mod self_destruct_state;
Expand Down
118 changes: 118 additions & 0 deletions engine-tests/src/tests/relayer_keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use crate::prelude::U256;
use crate::test_utils::asserts::assert_execution_status_failure;
use crate::test_utils::{str_to_account_id, AuroraRunner};
use aurora_engine::parameters::NewCallArgs;
use aurora_engine_types::types::ZERO_YOCTO;
use borsh::BorshSerialize;
use near_crypto::PublicKey;
use near_primitives::account::AccessKeyPermission;
use near_sdk_sim::{ExecutionResult, UserAccount};
use std::str::FromStr;

const PUBLIC_KEY: &str = "ed25519:3gyjNWQWMZNrzqWLhwxzQqfeDFyd3KhXjzmwCqzVCRuF";
const PUBLIC_KEY_BUDGET: u128 = 1_000_000;

// there are multiple deploy_evm implementations but their API is not good enough
// TODO replace with near-workspaces
fn deploy_evm_with_relayer() -> AuroraAccount {
let aurora_runner = AuroraRunner::default();
let main_account = near_sdk_sim::init_simulator(None);

let sim_aurora_account = format!(
"{}.{}",
aurora_runner.aurora_account_id,
main_account.account_id()
);
let contract_account = main_account.deploy(
aurora_runner.code.code(),
sim_aurora_account.parse().unwrap(),
5 * near_sdk_sim::STORAGE_AMOUNT,
);
let prover_account = str_to_account_id("prover.near");

let new_args = NewCallArgs {
chain_id: crate::prelude::u256_to_arr(&U256::from(aurora_runner.chain_id)),
owner_id: str_to_account_id(main_account.account_id.as_str()),
bridge_prover_id: prover_account,
upgrade_delay_blocks: 1,
};
main_account
.call(
contract_account.account_id.clone(),
"new",
&new_args.try_to_vec().unwrap(),
near_sdk_sim::DEFAULT_GAS,
0,
)
.assert_success();

AuroraAccount {
owner: main_account,
contract: contract_account,
}
}

pub struct AuroraAccount {
pub owner: UserAccount,
pub contract: UserAccount,
}

fn add_relayer_key_call(user: &UserAccount, runner: &AuroraAccount) -> ExecutionResult {
user.call(
runner.contract.account_id.clone(),
"add_relayer_key",
format!("{{\"public_key\": \"{PUBLIC_KEY}\"}}").as_bytes(),
near_sdk_sim::DEFAULT_GAS,
PUBLIC_KEY_BUDGET,
)
}

fn remove_relayer_key_call(user: &UserAccount, runner: &AuroraAccount) -> ExecutionResult {
user.call(
runner.contract.account_id.clone(),
"remove_relayer_key",
format!("{{\"public_key\": \"{PUBLIC_KEY}\"}}").as_bytes(),
near_sdk_sim::DEFAULT_GAS,
ZERO_YOCTO.as_u128(),
)
}

#[test]
fn test_relayer_keys_mgmt_access() {
let runner = deploy_evm_with_relayer();

let result = add_relayer_key_call(&runner.contract, &runner);
assert_execution_status_failure(
result.outcome().clone().status,
"ERR_NOT_ALLOWED",
"Expected failure as public key does not exist",
);
}

#[test]
fn test_relayer_keys_mgmt() {
let runner = deploy_evm_with_relayer();

add_relayer_key_call(&runner.owner, &runner).assert_success();

let pk = PublicKey::from_str(PUBLIC_KEY).unwrap();
let ak = runner
.contract
.borrow_runtime()
.view_access_key(runner.contract.account_id.clone().as_str(), &pk)
.unwrap();
let fk = match ak.permission {
AccessKeyPermission::FullAccess => panic!("Expected function access key"),
AccessKeyPermission::FunctionCall(fk) => fk,
};
assert_eq!(fk.allowance.unwrap(), PUBLIC_KEY_BUDGET);
assert_eq!(fk.method_names.join(","), "submit");

remove_relayer_key_call(&runner.owner, &runner).assert_success();
let ak = runner
.contract
.borrow_runtime()
.view_access_key(runner.contract.account_id.clone().as_str(), &pk);

assert_eq!(ak, None);
}
2 changes: 2 additions & 0 deletions engine-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ hex = { version = "0.4", default-features = false, features = ["alloc"] }
primitive-types = { version = "0.12", default-features = false, features = ["rlp", "serde_no_std"] }
serde = { version = "1", default-features = false, features = ["alloc", "derive"] }
serde_json = { version = "1", default-features = false, features = ["alloc"] }
bs58 = { version = "0.4.0", default-features = false, features = ["alloc", "sha2"] }


[dev-dependencies]
rand = "0.8.5"
Expand Down
1 change: 1 addition & 0 deletions engine-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

pub mod account_id;
pub mod parameters;
pub mod public_key;
pub mod storage;
pub mod types;

Expand Down
Loading