Skip to content

Commit

Permalink
impl
Browse files Browse the repository at this point in the history
  • Loading branch information
pugachAG committed Jan 14, 2025
1 parent cf45cc5 commit d807d7b
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 3 deletions.
3 changes: 3 additions & 0 deletions chain/rosetta-rpc/src/adapters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,9 @@ impl From<NearActions> for Vec<crate::models::Operation> {

operations.extend(delegated_operations);
} // TODO(#8469): Implement delegate action support, for now they are ignored.
near_primitives::transaction::Action::DeployGlobalContract(_action) => {
// TODO(#12639): Implement global contract deploys support, ignored for now.
}
}
}
operations
Expand Down
2 changes: 2 additions & 0 deletions core/primitives-core/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ pub enum ProtocolFeature {
ExcludeExistingCodeFromWitnessForCodeLen,
/// Use the block height instead of the block hash to calculate the receipt ID.
BlockHeightForReceiptId,
GlobalContracts,
}

impl ProtocolFeature {
Expand Down Expand Up @@ -286,6 +287,7 @@ impl ProtocolFeature {
ProtocolFeature::ExcludeExistingCodeFromWitnessForCodeLen => 148,
ProtocolFeature::BlockHeightForReceiptId => 149,
// Place features that are not yet in Nightly below this line.
ProtocolFeature::GlobalContracts => 200,
}
}

Expand Down
37 changes: 37 additions & 0 deletions core/primitives/src/action/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,36 @@ impl fmt::Debug for DeployContractAction {
}
}

/// Deploy global contract action
#[serde_as]
#[derive(
BorshSerialize,
BorshDeserialize,
serde::Serialize,
serde::Deserialize,
PartialEq,
Eq,
Clone,
ProtocolSchema,
)]
pub struct DeployGlobalContractAction {
/// WebAssembly binary
#[serde_as(as = "Base64")]
pub code: Vec<u8>,

/// Enables global contract code to referenced by owner account id
/// instead of code hash
pub link_account: bool,
}

impl fmt::Debug for DeployGlobalContractAction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DeployGlobalContractAction")
.field("code", &format_args!("{}", base64(&self.code)))
.finish()
}
}

#[serde_as]
#[derive(
BorshSerialize,
Expand Down Expand Up @@ -216,6 +246,7 @@ pub enum Action {
DeleteKey(Box<DeleteKeyAction>),
DeleteAccount(DeleteAccountAction),
Delegate(Box<delegate::SignedDelegateAction>),
DeployGlobalContract(DeployGlobalContractAction),
#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")]
/// Makes a non-refundable transfer for storage allowance.
/// Only possible during new account creation.
Expand Down Expand Up @@ -261,6 +292,12 @@ impl From<DeployContractAction> for Action {
}
}

impl From<DeployGlobalContractAction> for Action {
fn from(deploy_global_contract_action: DeployGlobalContractAction) -> Self {
Self::DeployGlobalContract(deploy_global_contract_action)
}
}

impl From<FunctionCallAction> for Action {
fn from(function_call_action: FunctionCallAction) -> Self {
Self::FunctionCall(Box::new(function_call_action))
Expand Down
13 changes: 13 additions & 0 deletions core/primitives/src/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//! from the source structure in the relevant `From<SourceStruct>` impl.
use crate::account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission};
use crate::action::delegate::{DelegateAction, SignedDelegateAction};
use crate::action::DeployGlobalContractAction;
use crate::bandwidth_scheduler::BandwidthRequests;
use crate::block::{Block, BlockHeader, Tip};
use crate::block_header::BlockHeaderInnerLite;
Expand Down Expand Up @@ -1170,6 +1171,11 @@ pub enum ActionView {
delegate_action: DelegateAction,
signature: Signature,
},
DeployGlobalContract {
#[serde_as(as = "Base64")]
code: Vec<u8>,
link_account: bool,
},
}

impl From<Action> for ActionView {
Expand Down Expand Up @@ -1206,6 +1212,10 @@ impl From<Action> for ActionView {
delegate_action: action.delegate_action,
signature: action.signature,
},
Action::DeployGlobalContract(action) => {
let code = hash(&action.code).as_ref().to_vec();
ActionView::DeployGlobalContract { code, link_account: action.link_account }
}
}
}
}
Expand Down Expand Up @@ -1247,6 +1257,9 @@ impl TryFrom<ActionView> for Action {
ActionView::Delegate { delegate_action, signature } => {
Action::Delegate(Box::new(SignedDelegateAction { delegate_action, signature }))
}
ActionView::DeployGlobalContract { code, link_account } => {
Action::DeployGlobalContract(DeployGlobalContractAction { code, link_account })
}
})
}
}
Expand Down
20 changes: 18 additions & 2 deletions runtime/runtime/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use near_crypto::PublicKey;
use near_parameters::{AccountCreationConfig, ActionCosts, RuntimeConfig, RuntimeFeesConfig};
use near_primitives::account::{AccessKey, AccessKeyPermission, Account};
use near_primitives::action::delegate::{DelegateAction, SignedDelegateAction};
use near_primitives::action::DeployGlobalContractAction;
use near_primitives::checked_feature;
use near_primitives::config::ViewConfig;
use near_primitives::errors::{ActionError, ActionErrorKind, InvalidAccessKeyError, RuntimeError};
Expand Down Expand Up @@ -653,6 +654,16 @@ pub(crate) fn action_deploy_contract(
Ok(())
}

pub(crate) fn action_deploy_global_contract(
_account_id: &AccountId,
_deploy_contract: &DeployGlobalContractAction,
_result: &mut ActionResult,
) -> Result<(), StorageError> {
let _span = tracing::debug_span!(target: "runtime", "action_deploy_global_contract").entered();
// TODO(#12715): implement global contract distribution
Ok(())
}

pub(crate) fn action_delete_account(
state_update: &mut TrieUpdate,
account: &mut Option<Account>,
Expand Down Expand Up @@ -1025,7 +1036,11 @@ pub(crate) fn check_actor_permissions(
account_id: &AccountId,
) -> Result<(), ActionError> {
match action {
Action::DeployContract(_) | Action::Stake(_) | Action::AddKey(_) | Action::DeleteKey(_) => {
Action::DeployContract(_)
| Action::Stake(_)
| Action::AddKey(_)
| Action::DeleteKey(_)
| Action::DeployGlobalContract(_) => {
if actor_id != account_id {
return Err(ActionErrorKind::ActorNoPermission {
account_id: account_id.clone(),
Expand Down Expand Up @@ -1137,7 +1152,8 @@ pub(crate) fn check_account_existence(
| Action::AddKey(_)
| Action::DeleteKey(_)
| Action::DeleteAccount(_)
| Action::Delegate(_) => {
| Action::Delegate(_)
| Action::DeployGlobalContract(_) => {
if account.is_none() {
return Err(ActionErrorKind::AccountDoesNotExist {
account_id: account_id.clone(),
Expand Down
8 changes: 8 additions & 0 deletions runtime/runtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ pub fn total_send_fees(
&delegate_action.receiver_id,
)?
}
DeployGlobalContract(_deploy_global_contract_action) => {
// TODO(#12717): implement send fees for global contract deploy
1
}
};
result = safe_add_gas(result, delta)?;
}
Expand Down Expand Up @@ -241,6 +245,10 @@ pub fn exec_fee(config: &RuntimeConfig, action: &Action, receiver_id: &AccountId
DeleteKey(_) => fees.fee(ActionCosts::delete_key).exec_fee(),
DeleteAccount(_) => fees.fee(ActionCosts::delete_account).exec_fee(),
Delegate(_) => fees.fee(ActionCosts::delegate).exec_fee(),
DeployGlobalContract(_deploy_global_contract_action) => {
// TODO(#12717): implement exec fee for global contract deploys
1
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions runtime/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,9 @@ impl Runtime {
apply_state.current_protocol_version,
)?;
}
Action::DeployGlobalContract(deploy_global_contract) => {
action_deploy_global_contract(account_id, deploy_global_contract, &mut result)?;
}
Action::FunctionCall(function_call) => {
let account = account.as_mut().expect(EXPECT_ACCOUNT_EXISTS);
let contract = preparation_pipeline.get_contract(
Expand Down
3 changes: 2 additions & 1 deletion runtime/runtime/src/pipelining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ impl ReceiptPreparationPipeline {
| Action::Stake(_)
| Action::AddKey(_)
| Action::DeleteKey(_)
| Action::DeleteAccount(_) => {}
| Action::DeleteAccount(_)
| Action::DeployGlobalContract(_) => {}
#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")]
Action::NonrefundableStorageTransfer(_) => {}
}
Expand Down
26 changes: 26 additions & 0 deletions runtime/runtime/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use near_crypto::key_conversion::is_valid_staking_key;
use near_parameters::RuntimeConfig;
use near_primitives::account::AccessKeyPermission;
use near_primitives::action::delegate::SignedDelegateAction;
use near_primitives::action::DeployGlobalContractAction;
use near_primitives::checked_feature;
use near_primitives::errors::{
ActionsValidationError, InvalidAccessKeyError, InvalidTxError, ReceiptValidationError,
Expand Down Expand Up @@ -438,6 +439,9 @@ pub fn validate_action(
match action {
Action::CreateAccount(_) => Ok(()),
Action::DeployContract(a) => validate_deploy_contract_action(limit_config, a),
Action::DeployGlobalContract(a) => {
validate_deploy_global_contract_action(limit_config, a, current_protocol_version)
}
Action::FunctionCall(a) => validate_function_call_action(limit_config, a),
Action::Transfer(_) => Ok(()),
#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")]
Expand Down Expand Up @@ -477,6 +481,28 @@ fn validate_deploy_contract_action(
Ok(())
}

/// Validates `DeployGlobalContractAction`. Checks that the given contract size doesn't exceed the limit.
fn validate_deploy_global_contract_action(
limit_config: &LimitConfig,
action: &DeployGlobalContractAction,
current_protocol_version: ProtocolVersion,
) -> Result<(), ActionsValidationError> {
if !checked_feature!("stable", GlobalContracts, current_protocol_version) {
return Err(ActionsValidationError::UnsupportedProtocolFeature {
protocol_feature: "GlobalContracts".to_owned(),
version: current_protocol_version,
});
}
if action.code.len() as u64 > limit_config.max_contract_size {
return Err(ActionsValidationError::ContractSizeExceeded {
size: action.code.len() as u64,
limit: limit_config.max_contract_size,
});
}

Ok(())
}

/// Validates `FunctionCallAction`. Checks that the method name length doesn't exceed the limit and
/// the length of the arguments doesn't exceed the limit.
fn validate_function_call_action(
Expand Down
4 changes: 4 additions & 0 deletions tools/state-viewer/src/contract_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ pub(crate) enum ActionType {
DeleteAccount,
DataReceipt,
Delegate,
DeployGlobalContract,
}

impl ContractAccount {
Expand Down Expand Up @@ -348,6 +349,9 @@ fn try_find_actions_spawned_by_receipt(
Action::DeleteKey(_) => ActionType::DeleteKey,
Action::DeleteAccount(_) => ActionType::DeleteAccount,
Action::Delegate(_) => ActionType::Delegate,
Action::DeployGlobalContract(_) => {
ActionType::DeployGlobalContract
}
};
entry
.actions
Expand Down

0 comments on commit d807d7b

Please sign in to comment.