Skip to content

Commit

Permalink
chore!: upgrade to 0.25 release (#1242)
Browse files Browse the repository at this point in the history
  • Loading branch information
akorchyn authored Sep 4, 2024
1 parent 0be2c71 commit df12263
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 32 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ jobs:
matrix:
platform:
- os: ubuntu-latest
rs: 1.78
rs: 1.79
- os: ubuntu-latest
rs: stable
- os: macos-latest
rs: 1.78
rs: 1.79
- os: macos-latest
rs: stable
features: ['', '--features unstable,legacy,__abi-generate']
Expand Down
12 changes: 6 additions & 6 deletions near-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
near-sdk-macros = { path = "../near-sdk-macros", version = "~5.3.0" }
near-sys = { path = "../near-sys", version = "0.2.2" }
base64 = "0.21"
base64 = "0.22"
borsh = { version = "1.0.0", features = ["derive"] }
bs58 = "0.5"

Expand All @@ -42,11 +42,11 @@ schemars = { version = "0.8.8", optional = true }
near-abi = { version = "0.4.0", features = [
"__chunked-entries",
], optional = true }
near-vm-runner = { version = "0.24", optional = true }
near-primitives-core = { version = "0.24", optional = true }
near-primitives = { version = "0.24", optional = true }
near-crypto = { version = "0.24", default-features = false, optional = true }
near-parameters = { version = "0.24", optional = true }
near-vm-runner = { version = "0.25", optional = true }
near-primitives-core = { version = "0.25", optional = true }
near-primitives = { version = "0.25", optional = true }
near-crypto = { version = "0.25", default-features = false, optional = true }
near-parameters = { version = "0.25", optional = true }

[dev-dependencies]
near-sdk = { path = ".", features = ["legacy", "unit-testing"] }
Expand Down
142 changes: 118 additions & 24 deletions near-sdk/src/environment/mock/mocked_blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,41 @@ use near_parameters::{RuntimeConfigStore, RuntimeFeesConfig};
use near_primitives_core::version::PROTOCOL_VERSION;
use near_vm_runner::logic::mocks::mock_external::MockedExternal;
use near_vm_runner::logic::types::{PromiseResult as VmPromiseResult, ReceiptIndex};
use near_vm_runner::logic::{External, MemoryLike, VMLogic};
use near_vm_runner::logic::{ExecutionResultState, External, MemoryLike, VMLogic};
use std::cell::RefCell;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::sync::Arc;

/// Mocked blockchain that can be used in the tests for the smart contracts.
/// It implements `BlockchainInterface` by redirecting calls to `VMLogic`. It unwraps errors of
/// `VMLogic` to cause panic during the unit tests similarly to how errors of `VMLogic` would cause
/// the termination of guest program execution. Unit tests can even assert the expected error
/// message.
pub struct MockedBlockchain {
pub struct MockedBlockchain<Memory = MockedMemory>
where
Memory: MemoryLike + Default + 'static,
{
logic: RefCell<VMLogic<'static>>,
// We keep ownership over logic fixture so that references in `VMLogic` are valid.
#[allow(dead_code)]
logic_fixture: LogicFixture,
_memory: PhantomData<Memory>,
}

pub fn test_vm_config() -> near_parameters::vm::Config {
let store = RuntimeConfigStore::test();
let config = store.get_config(PROTOCOL_VERSION).wasm_config.clone();
let config = store.get_config(PROTOCOL_VERSION).wasm_config.as_ref().to_owned();
near_parameters::vm::Config {
vm_kind: config.vm_kind.replace_with_wasmtime_if_unsupported(),
..config
}
}

impl Default for MockedBlockchain {
impl<T> Default for MockedBlockchain<T>
where
T: MemoryLike + Default + 'static,
{
fn default() -> Self {
MockedBlockchain::new(
VMContextBuilder::new().build(),
Expand All @@ -50,50 +59,50 @@ impl Default for MockedBlockchain {

struct LogicFixture {
ext: Box<MockedExternal>,
memory: Box<dyn MemoryLike>,
#[allow(clippy::box_collection)]
promise_results: Box<Vec<VmPromiseResult>>,
config: Box<near_parameters::vm::Config>,
fees_config: Box<RuntimeFeesConfig>,
fees_config: Arc<RuntimeFeesConfig>,
context: Box<near_vm_runner::logic::VMContext>,
}

impl MockedBlockchain {
impl<Memory> MockedBlockchain<Memory>
where
Memory: MemoryLike + Default + 'static,
{
pub fn new(
context: VMContext,
config: near_parameters::vm::Config,
fees_config: RuntimeFeesConfig,
promise_results: Vec<PromiseResult>,
storage: HashMap<Vec<u8>, Vec<u8>>,
validators: HashMap<String, NearToken>,
memory_opt: Option<Box<dyn MemoryLike>>,
memory: Option<Memory>,
) -> Self {
let mut ext = Box::new(MockedExternal::new());
let context = Box::new(sdk_context_to_vm_context(context));
let promise_results: Arc<[VmPromiseResult]> =
promise_results.into_iter().map(Into::into).collect::<Vec<_>>().into();
let context: Box<near_vm_runner::logic::VMContext> =
Box::new(sdk_context_to_vm_context(context, promise_results));
ext.fake_trie = storage;
ext.validators =
validators.into_iter().map(|(k, v)| (k.parse().unwrap(), v.as_yoctonear())).collect();
let memory = memory_opt.unwrap_or_else(|| Box::<MockedMemory>::default());
let promise_results = Box::new(promise_results.into_iter().map(From::from).collect());
let config = Box::new(config);
let fees_config = Box::new(fees_config);
let config = Arc::new(config);
let fees_config = Arc::new(fees_config);
let result_state =
ExecutionResultState::new(&context, context.make_gas_counter(&config), config.clone());

let mut logic_fixture =
LogicFixture { ext, memory, context, promise_results, config, fees_config };
let mut logic_fixture = LogicFixture { ext, context, fees_config };

let logic = unsafe {
VMLogic::new(
&mut *(logic_fixture.ext.as_mut() as *mut dyn External),
&*(logic_fixture.context.as_mut() as *mut near_vm_runner::logic::VMContext),
&*(logic_fixture.config.as_mut() as *const near_parameters::vm::Config),
&*(logic_fixture.fees_config.as_mut() as *const RuntimeFeesConfig),
&*(logic_fixture.promise_results.as_ref().as_slice() as *const [VmPromiseResult]),
&mut *(logic_fixture.memory.as_mut() as *mut dyn MemoryLike),
logic_fixture.fees_config.clone(),
result_state,
memory.unwrap_or_default(),
)
};

let logic = RefCell::new(logic);
Self { logic, logic_fixture }
Self { logic, logic_fixture, _memory: PhantomData }
}

pub fn take_storage(&mut self) -> HashMap<Vec<u8>, Vec<u8>> {
Expand Down Expand Up @@ -147,7 +156,10 @@ impl MockedBlockchain {
}
}

fn sdk_context_to_vm_context(context: VMContext) -> near_vm_runner::logic::VMContext {
fn sdk_context_to_vm_context(
context: VMContext,
promise_results: std::sync::Arc<[VmPromiseResult]>,
) -> near_vm_runner::logic::VMContext {
near_vm_runner::logic::VMContext {
current_account_id: context.current_account_id.as_str().parse().unwrap(),
signer_account_id: context.signer_account_id.as_str().parse().unwrap(),
Expand All @@ -169,12 +181,14 @@ fn sdk_context_to_vm_context(context: VMContext) -> near_vm_runner::logic::VMCon
.into_iter()
.map(|a| a.as_str().parse().unwrap())
.collect(),
promise_results,
}
}

#[cfg(not(target_arch = "wasm32"))]
mod mock_chain {
use near_vm_runner::logic::{errors::VMLogicError, VMLogic};

fn with_mock_interface<F, R>(f: F) -> R
where
F: FnOnce(&mut VMLogic) -> Result<R, VMLogicError>,
Expand Down Expand Up @@ -588,3 +602,83 @@ mod mock_chain {
with_mock_interface(|b| b.alt_bn128_pairing_check(value_len, value_ptr))
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;

use near_gas::NearGas;
use near_primitives::types::GasWeight;

use crate::{
env,
test_utils::{accounts, get_created_receipts, get_logs},
testing_env,
};

use super::*;

#[test]
fn test_mocked_blockchain_api() {
let public_key: crate::types::PublicKey =
"ed25519:H3C2AVAWKq5Qm7FkyDB5cHKcYKHgbiiB2BzX8DQX8CJ".parse().unwrap();
let context = VMContextBuilder::new()
.signer_account_id(accounts(0))
.signer_account_pk(public_key.clone())
.build();

testing_env!(context.clone());
assert_eq!(env::signer_account_id(), accounts(0));
assert_eq!(env::signer_account_pk(), public_key);

env::storage_write(b"smile", b"hello_worlds");
assert_eq!(env::storage_read(b"smile").unwrap(), b"hello_worlds");
assert!(env::storage_has_key(b"smile"));
env::storage_remove(b"smile");
assert!(!env::storage_has_key(b"smile"));

let promise_index = env::promise_create(
"account.near".parse().unwrap(),
"method",
&[],
NearToken::from_millinear(1),
NearGas::from_tgas(1),
);

env::promise_batch_action_stake(promise_index, NearToken::from_millinear(1), &public_key);

env::log_str("logged");

let logs = get_logs();
assert_eq!(logs.len(), 1);
assert_eq!(logs[0], "logged");

let actions = get_created_receipts();
assert_eq!(actions.len(), 1);
assert_eq!(actions[0].receiver_id.to_string(), "account.near");
assert_eq!(actions[0].actions.len(), 2);
assert_eq!(
actions[0].actions[0],
MockAction::FunctionCallWeight {
receipt_index: 0,
method_name: b"method".to_vec(),
args: [].to_vec(),
attached_deposit: NearToken::from_millinear(1),
prepaid_gas: NearGas::from_tgas(1),
gas_weight: GasWeight(0)
}
);

assert_eq!(
actions[0].actions[1],
MockAction::Stake {
receipt_index: 0,
stake: NearToken::from_millinear(1),
public_key: near_crypto::PublicKey::from_str(
"ed25519:H3C2AVAWKq5Qm7FkyDB5cHKcYKHgbiiB2BzX8DQX8CJ"
)
.unwrap()
}
);
}
}

0 comments on commit df12263

Please sign in to comment.