diff --git a/core/primitives-core/src/serialize.rs b/core/primitives-core/src/serialize.rs index db3c7a21978..120e1c831b3 100644 --- a/core/primitives-core/src/serialize.rs +++ b/core/primitives-core/src/serialize.rs @@ -24,13 +24,12 @@ pub mod base64_format { serializer.serialize_str(&to_base64(data)) } - pub fn deserialize<'de, D, T>(deserializer: D) -> Result + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, - T: From>, { let s = String::deserialize(deserializer)?; - from_base64(&s).map_err(|err| de::Error::custom(err.to_string())).map(Into::into) + from_base64(&s).map_err(|err| de::Error::custom(err.to_string())) } } diff --git a/core/primitives/src/state_record.rs b/core/primitives/src/state_record.rs index 62da28a869c..7b96a7c9c12 100644 --- a/core/primitives/src/state_record.rs +++ b/core/primitives/src/state_record.rs @@ -9,7 +9,7 @@ use crate::trie_key::trie_key_parsers::{ parse_account_id_from_received_data_key, parse_data_id_from_received_data_key, parse_data_key_from_contract_data_key, parse_public_key_from_access_key_key, }; -use crate::types::AccountId; +use crate::types::{AccountId, StoreKey, StoreValue}; use borsh::BorshDeserialize; use near_crypto::PublicKey; use std::fmt::{Display, Formatter}; @@ -20,13 +20,7 @@ pub enum StateRecord { /// Account information. Account { account_id: AccountId, account: Account }, /// Data records inside the contract, encoded in base64. - Data { - account_id: AccountId, - #[serde(with = "base64_format")] - data_key: Vec, - #[serde(with = "base64_format")] - value: Vec, - }, + Data { account_id: AccountId, data_key: StoreKey, value: StoreValue }, /// Contract code encoded in base64. Contract { account_id: AccountId, @@ -63,7 +57,11 @@ impl StateRecord { col::CONTRACT_DATA => { let account_id = parse_account_id_from_contract_data_key(&key).unwrap(); let data_key = parse_data_key_from_contract_data_key(&key, &account_id).unwrap(); - Some(StateRecord::Data { account_id, data_key: data_key.to_vec(), value }) + Some(StateRecord::Data { + account_id, + data_key: data_key.to_vec().into(), + value: value.into(), + }) } col::CONTRACT_CODE => Some(StateRecord::Contract { account_id: parse_account_id_from_contract_code_key(&key).unwrap(), @@ -107,8 +105,8 @@ impl Display for StateRecord { f, "Storage {:?},{:?}: {:?}", account_id, - to_printable(data_key), - to_printable(value) + to_printable(data_key.as_ref()), + to_printable(value.as_ref()) ), StateRecord::Contract { account_id, code: _ } => { write!(f, "Code for {:?}: ...", account_id) diff --git a/core/primitives/src/types.rs b/core/primitives/src/types.rs index 7ad2480b30d..0b90e361050 100644 --- a/core/primitives/src/types.rs +++ b/core/primitives/src/types.rs @@ -3,10 +3,10 @@ use crate::challenge::ChallengesResult; use crate::errors::EpochError; use crate::hash::CryptoHash; use crate::receipt::Receipt; +use crate::serialize::base64_format; use crate::serialize::dec_format; use crate::trie_key::TrieKey; use borsh::{BorshDeserialize, BorshSerialize}; -use derive_more::{AsRef as DeriveAsRef, From as DeriveFrom}; use near_crypto::PublicKey; /// Reexport primitive types pub use near_primitives_core::types::*; @@ -50,20 +50,40 @@ pub struct AccountInfo { /// NOTE: Currently, this type is only used in the view_client and RPC to be able to transparently /// pretty-serialize the bytes arrays as base64-encoded strings (see `serialize.rs`). #[derive( - Debug, Clone, PartialEq, Eq, DeriveAsRef, DeriveFrom, BorshSerialize, BorshDeserialize, + serde::Serialize, + serde::Deserialize, + Clone, + Debug, + PartialEq, + Eq, + derive_more::Deref, + derive_more::From, + derive_more::Into, + BorshSerialize, + BorshDeserialize, )] -#[as_ref(forward)] -pub struct StoreKey(Vec); +#[serde(transparent)] +pub struct StoreKey(#[serde(with = "base64_format")] Vec); /// This type is used to mark values returned from store (arrays of bytes). /// /// NOTE: Currently, this type is only used in the view_client and RPC to be able to transparently /// pretty-serialize the bytes arrays as base64-encoded strings (see `serialize.rs`). #[derive( - Debug, Clone, PartialEq, Eq, DeriveAsRef, DeriveFrom, BorshSerialize, BorshDeserialize, + serde::Serialize, + serde::Deserialize, + Clone, + Debug, + PartialEq, + Eq, + derive_more::Deref, + derive_more::From, + derive_more::Into, + BorshSerialize, + BorshDeserialize, )] -#[as_ref(forward)] -pub struct StoreValue(Vec); +#[serde(transparent)] +pub struct StoreValue(#[serde(with = "base64_format")] Vec); /// This type is used to mark function arguments. /// @@ -71,10 +91,20 @@ pub struct StoreValue(Vec); /// transparently serialized and deserialized as a base64-encoded string when serde is used /// (serde_json). #[derive( - Debug, Clone, PartialEq, Eq, DeriveAsRef, DeriveFrom, BorshSerialize, BorshDeserialize, + serde::Serialize, + serde::Deserialize, + Clone, + Debug, + PartialEq, + Eq, + derive_more::Deref, + derive_more::From, + derive_more::Into, + BorshSerialize, + BorshDeserialize, )] -#[as_ref(forward)] -pub struct FunctionArgs(Vec); +#[serde(transparent)] +pub struct FunctionArgs(#[serde(with = "base64_format")] Vec); /// A structure used to indicate the kind of state changes due to transaction/receipt processing, etc. #[derive(Debug, Clone, BorshSerialize, BorshDeserialize)] @@ -441,7 +471,7 @@ impl StateRootNode { PartialEq, PartialOrd, Ord, - DeriveAsRef, + derive_more::AsRef, BorshSerialize, BorshDeserialize, serde::Serialize, diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index f2b66fcd657..04285d968b4 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -215,10 +215,8 @@ impl From for AccessKey { /// Item of the state, key and value are serialized in base64 and proof for inclusion of given state item. #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)] pub struct StateItem { - #[serde(with = "base64_format")] - pub key: Vec, - #[serde(with = "base64_format")] - pub value: Vec, + pub key: StoreKey, + pub value: StoreValue, /// Deprecated, always empty, eventually will be deleted. // TODO(mina86): This was deprecated in 1.30. Get rid of the field // altogether at 1.33 or something. @@ -306,7 +304,7 @@ pub enum QueryRequest { }, ViewState { account_id: AccountId, - #[serde(rename = "prefix_base64", with = "base64_format")] + #[serde(rename = "prefix_base64")] prefix: StoreKey, #[serde(default, skip_serializing_if = "is_false")] include_proof: bool, @@ -321,7 +319,7 @@ pub enum QueryRequest { CallFunction { account_id: AccountId, method_name: String, - #[serde(rename = "args_base64", with = "base64_format")] + #[serde(rename = "args_base64")] args: FunctionArgs, }, } @@ -1111,8 +1109,7 @@ pub enum ActionView { }, FunctionCall { method_name: String, - #[serde(with = "base64_format")] - args: Vec, + args: FunctionArgs, gas: Gas, #[serde(with = "dec_format")] deposit: Balance, @@ -1152,7 +1149,7 @@ impl From for ActionView { } Action::FunctionCall(action) => ActionView::FunctionCall { method_name: action.method_name, - args: action.args, + args: action.args.into(), gas: action.gas, deposit: action.deposit, }, @@ -1186,7 +1183,12 @@ impl TryFrom for Action { Action::DeployContract(DeployContractAction { code }) } ActionView::FunctionCall { method_name, args, gas, deposit } => { - Action::FunctionCall(FunctionCallAction { method_name, args, gas, deposit }) + Action::FunctionCall(FunctionCallAction { + method_name, + args: args.into(), + gas, + deposit, + }) } ActionView::Transfer { deposit } => Action::Transfer(TransferAction { deposit }), ActionView::Stake { stake, public_key } => { @@ -2036,7 +2038,7 @@ pub enum StateChangesRequestView { }, DataChanges { account_ids: Vec, - #[serde(rename = "key_prefix_base64", with = "base64_format")] + #[serde(rename = "key_prefix_base64")] key_prefix: StoreKey, }, } @@ -2160,14 +2162,14 @@ pub enum StateChangeValueView { }, DataUpdate { account_id: AccountId, - #[serde(rename = "key_base64", with = "base64_format")] + #[serde(rename = "key_base64")] key: StoreKey, - #[serde(rename = "value_base64", with = "base64_format")] + #[serde(rename = "value_base64")] value: StoreValue, }, DataDeletion { account_id: AccountId, - #[serde(rename = "key_base64", with = "base64_format")] + #[serde(rename = "key_base64")] key: StoreKey, }, ContractCodeUpdate { diff --git a/integration-tests/src/tests/client/sandbox.rs b/integration-tests/src/tests/client/sandbox.rs index 720c54fad16..b7b5ecb6a98 100644 --- a/integration-tests/src/tests/client/sandbox.rs +++ b/integration-tests/src/tests/client/sandbox.rs @@ -91,13 +91,13 @@ fn test_patch_state() { env.clients[0].chain.patch_state(SandboxStatePatch::new(vec![StateRecord::Data { account_id: "test0".parse().unwrap(), data_key: state_item.key, - value: b"world".to_vec(), + value: b"world".to_vec().into(), }])); do_blocks(&mut env, 9, 20); let state = env.query_state("test0".parse().unwrap()); assert_eq!(state.len(), 1); - assert_eq!(state[0].value, b"world"); + assert_eq!(state[0].value.as_slice(), b"world"); } #[test] diff --git a/integration-tests/src/tests/runtime/state_viewer.rs b/integration-tests/src/tests/runtime/state_viewer.rs index 6ef65123ff7..0c447c67f6d 100644 --- a/integration-tests/src/tests/runtime/state_viewer.rs +++ b/integration-tests/src/tests/runtime/state_viewer.rs @@ -200,7 +200,11 @@ fn assert_view_state( let values = want_values .iter() - .map(|(key, value)| StateItem { key: key.to_vec(), value: value.to_vec(), proof: vec![] }) + .map(|(key, value)| StateItem { + key: key.to_vec().into(), + value: value.to_vec().into(), + proof: vec![], + }) .collect::>(); let view_state = diff --git a/integration-tests/src/tests/standard_cases/runtime.rs b/integration-tests/src/tests/standard_cases/runtime.rs index ae75364de01..a5cae097047 100644 --- a/integration-tests/src/tests/standard_cases/runtime.rs +++ b/integration-tests/src/tests/standard_cases/runtime.rs @@ -29,8 +29,8 @@ fn create_runtime_with_expensive_storage() -> RuntimeNode { } records.push(StateRecord::Data { account_id: bob_account(), - data_key: b"test".to_vec(), - value: b"123".to_vec(), + data_key: b"test".to_vec().into(), + value: b"123".to_vec().into(), }); RuntimeNode::new_from_genesis_and_config(&alice_account(), genesis, runtime_config) } diff --git a/runtime/runtime/src/genesis.rs b/runtime/runtime/src/genesis.rs index 8ed48a1cb0b..b902b9194dc 100644 --- a/runtime/runtime/src/genesis.rs +++ b/runtime/runtime/src/genesis.rs @@ -191,10 +191,10 @@ impl GenesisStateApplier { storage.modify(|state_update| { state_update.set( TrieKey::ContractData { - key: data_key.clone(), + key: data_key.clone().into(), account_id: account_id.clone(), }, - value.clone(), + value.clone().into(), ); }) } diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index d9468037910..56a89297b57 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -1526,7 +1526,7 @@ impl Runtime { set_account(state_update, account_id, &account); } StateRecord::Data { account_id, data_key, value } => { - state_update.set(TrieKey::ContractData { key: data_key, account_id }, value); + state_update.set(TrieKey::ContractData { key: data_key.into(), account_id }, value.into()); } StateRecord::Contract { account_id, code } => { let acc = get_account(state_update, &account_id).expect("Failed to read state").expect("Code state record should be preceded by the corresponding account record"); diff --git a/runtime/runtime/src/state_viewer/mod.rs b/runtime/runtime/src/state_viewer/mod.rs index bd16a3d9844..30c9c61f0b7 100644 --- a/runtime/runtime/src/state_viewer/mod.rs +++ b/runtime/runtime/src/state_viewer/mod.rs @@ -149,8 +149,8 @@ impl TrieViewer { for item in &mut iter { let (key, value) = item?; values.push(StateItem { - key: key[acc_sep_len..].to_vec(), - value: value, + key: key[acc_sep_len..].to_vec().into(), + value: value.into(), proof: vec![], }); } diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index d4c05775d7a..eca136d0a58 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -274,7 +274,7 @@ pub(crate) fn dump_account_storage( let record = StateRecord::from_raw_key_value(key.to_vec(), value).unwrap(); match record { StateRecord::Data { account_id: _, data_key: _, value } => { - fs::write(output, value).unwrap(); + fs::write(output, value.as_slice()).unwrap(); println!( "Dump contract storage under key {} of account {} into file {}", storage_key,