Skip to content

Commit

Permalink
Merge #4691
Browse files Browse the repository at this point in the history
4691: Migrate entry points r=darthsiroftardis a=darthsiroftardis

CHANGELOG:

- Removed field `entry_points` from the addressable entity
- Added a new trait function `migrate_entry_points` to `ext_entity`
- Added a new `Key::EntryPoint` and `StoredValue::EntryPoint` which allows for discrete records for an individual entry point

Co-authored-by: Karan Dhareshwar <[email protected]>
Co-authored-by: Michał Papierski <[email protected]>
Co-authored-by: Karan Dhareshwar <[email protected]>
  • Loading branch information
4 people authored May 5, 2024
2 parents 7317868 + 883cb7f commit 47cd7d3
Show file tree
Hide file tree
Showing 99 changed files with 3,597 additions and 1,274 deletions.
5 changes: 4 additions & 1 deletion execution_engine/src/execution/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use casper_types::{
bytesrepr,
execution::TransformError,
system, AccessRights, AddressableEntityHash, ApiError, ByteCodeHash, CLType, CLValueError,
EntityVersionKey, Key, PackageHash, StoredValueTypeMismatch, URef,
EntityVersionKey, Key, PackageHash, StoredValueTypeMismatch, TransactionRuntime, URef,
};
use casper_wasm::elements;

Expand Down Expand Up @@ -189,6 +189,9 @@ pub enum Error {
/// Invalid string encoding.
#[error("Invalid UTF-8 string encoding: {0}")]
InvalidUtf8Encoding(Utf8Error),
/// Incompatible transaction runtime.
#[error("Incompatible runtime: {0}")]
IncompatibleRuntime(TransactionRuntime),
}

impl From<PreprocessingError> for Error {
Expand Down
89 changes: 52 additions & 37 deletions execution_engine/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ use casper_types::{
},
AccessRights, ApiError, BlockGlobalAddr, BlockTime, ByteCode, ByteCodeAddr, ByteCodeHash,
ByteCodeKind, CLTyped, CLValue, ContextAccessRights, EntityAddr, EntityKind, EntityVersion,
EntityVersionKey, EntityVersions, Gas, GrantedAccess, Group, Groups, HostFunction,
HostFunctionCost, InitiatorAddr, Key, NamedArg, Package, PackageHash, PackageStatus, Phase,
PublicKey, RuntimeArgs, StoredValue, Tagged, Transfer, TransferResult, TransferV2,
TransferredTo, URef, DICTIONARY_ITEM_KEY_MAX_LENGTH, U512,
EntityVersionKey, EntityVersions, EntryPointAddr, EntryPointValue, Gas, GrantedAccess, Group,
Groups, HostFunction, HostFunctionCost, InitiatorAddr, Key, NamedArg, Package, PackageHash,
PackageStatus, Phase, PublicKey, RuntimeArgs, StoredValue, TransactionRuntime, Transfer,
TransferResult, TransferV2, TransferredTo, URef, DICTIONARY_ITEM_KEY_MAX_LENGTH, U512,
};

use crate::{
Expand Down Expand Up @@ -1158,18 +1158,18 @@ where
entry_point_name: &str,
args: RuntimeArgs,
) -> Result<CLValue, ExecError> {
let (entity, entity_hash, package) = match identifier {
let (entity, entity_addr, package) = match identifier {
CallContractIdentifier::Contract {
contract_hash: entity_hash,
} => {
let entity_key = if self.context.is_system_addressable_entity(&entity_hash)? {
Key::addressable_entity_key(EntityKindTag::System, entity_hash)
let entity_addr = if self.context.is_system_addressable_entity(&entity_hash)? {
EntityAddr::new_system(entity_hash.value())
} else {
Key::contract_entity_key(entity_hash)
EntityAddr::new_smart_contract(entity_hash.value())
};

let entity = if let Some(StoredValue::AddressableEntity(entity)) =
self.context.read_gs(&entity_key)?
self.context.read_gs(&Key::AddressableEntity(entity_addr))?
{
entity
} else {
Expand All @@ -1190,7 +1190,7 @@ where
return Err(ExecError::DisabledEntity(entity_hash));
}

(entity, entity_hash, package)
(entity, entity_addr, package)
}
CallContractIdentifier::ContractPackage {
contract_package_hash,
Expand Down Expand Up @@ -1224,21 +1224,21 @@ where
.copied()
.ok_or(ExecError::MissingEntityVersion(entity_version_key))?;

let entity_key = if self.context.is_system_addressable_entity(&entity_hash)? {
Key::addressable_entity_key(EntityKindTag::System, entity_hash)
let entity_addr = if self.context.is_system_addressable_entity(&entity_hash)? {
EntityAddr::new_system(entity_hash.value())
} else {
Key::contract_entity_key(entity_hash)
EntityAddr::new_smart_contract(entity_hash.value())
};

let entity = if let Some(StoredValue::AddressableEntity(entity)) =
self.context.read_gs(&entity_key)?
self.context.read_gs(&Key::AddressableEntity(entity_addr))?
{
entity
} else {
self.migrate_contract_and_contract_package(entity_hash)?
};

(entity, entity_hash, package)
(entity, entity_addr, package)
}
};

Expand All @@ -1256,10 +1256,27 @@ where
});
}

let entry_point = entity
.entry_point(entry_point_name)
.cloned()
.ok_or_else(|| ExecError::NoSuchMethod(entry_point_name.to_owned()))?;
// First check if we can fetch the discrete record
// if not use the method on the tracking copy to fetch the
// full set which also peeks the cache.
let entry_point = {
let entry_point_addr =
EntryPointAddr::new_v1_entry_point_addr(entity_addr, entry_point_name)?;
match self.context.read_gs(&Key::EntryPoint(entry_point_addr))? {
Some(StoredValue::EntryPoint(EntryPointValue::V1CasperVm(entry_point))) => {
entry_point
}
Some(_) | None => {
let entry_points = self
.context
.get_casper_vm_v1_entry_point(Key::AddressableEntity(entity_addr))?;
entry_points
.get(entry_point_name)
.cloned()
.ok_or_else(|| ExecError::NoSuchMethod(entry_point_name.to_owned()))?
}
}
};

let entry_point_type = entry_point.entry_point_type();

Expand Down Expand Up @@ -1302,6 +1319,8 @@ where
}
}

let entity_hash = AddressableEntityHash::new(entity_addr.value());

if !self
.context
.engine_config()
Expand Down Expand Up @@ -1363,8 +1382,6 @@ where
all_urefs
};

let entity_addr = entity.entity_addr(entity_hash);

let entity_named_keys = self
.context
.state()
Expand Down Expand Up @@ -1425,9 +1442,12 @@ where
EntityKind::System(_) | EntityKind::Account(_) => {
Key::ByteCode(ByteCodeAddr::Empty)
}
EntityKind::SmartContract => {
EntityKind::SmartContract(TransactionRuntime::VmCasperV1) => {
Key::ByteCode(ByteCodeAddr::new_wasm_addr(byte_code_addr))
}
EntityKind::SmartContract(runtime @ TransactionRuntime::VmCasperV2) => {
return Err(ExecError::IncompatibleRuntime(runtime))
}
};

let byte_code: ByteCode = match self.context.read_gs(&byte_code_key)? {
Expand All @@ -1439,11 +1459,9 @@ where
casper_wasm::deserialize_buffer(byte_code.bytes())?
};

let entity_tag = entity.kind().tag();

let mut named_keys = entity_named_keys;

let context_entity_key = Key::addressable_entity_key(entity_tag, entity_hash);
let context_entity_key = Key::AddressableEntity(entity_addr);

let context = self.context.new_from_self(
context_entity_key,
Expand Down Expand Up @@ -1748,9 +1766,9 @@ where
return Ok(Err(ApiError::NotAllowedToAddContractVersion));
}

if entry_points.contains_stored_session() {
return Err(ExecError::InvalidEntryPointType);
}
// if entry_points.contains_stored_session() {
// return Err(ExecError::InvalidEntryPointType);
// }

let mut package = self.context.get_package(package_hash)?;

Expand Down Expand Up @@ -1820,16 +1838,17 @@ where
named_keys.append(previous_named_keys);
self.context.write_named_keys(entity_addr, named_keys)?;

self.context.write_entry_points(entity_addr, entry_points)?;

let entity = AddressableEntity::new(
package_hash,
byte_code_hash.into(),
entry_points,
protocol_version,
main_purse,
associated_keys,
action_thresholds,
previous_message_topics.clone(),
EntityKind::SmartContract,
EntityKind::SmartContract(TransactionRuntime::VmCasperV1),
);

self.context.metered_write_gs_unsafe(entity_key, entity)?;
Expand Down Expand Up @@ -2487,13 +2506,11 @@ where
let package_hash = PackageHash::new(self.context.new_hash_address()?);
let main_purse = target_purse;
let associated_keys = AssociatedKeys::new(target, Weight::new(1));
let entry_points = EntryPoints::new();
let message_topics = MessageTopics::default();

let entity = AddressableEntity::new(
package_hash,
byte_code_hash,
entry_points,
protocol_version,
main_purse,
associated_keys,
Expand Down Expand Up @@ -2970,12 +2987,10 @@ where
let versions = package.versions();
for entity_hash in versions.contract_hashes() {
let entry_points = {
let entity: AddressableEntity = self
.context
.read_gs_typed(&Key::contract_entity_key(*entity_hash))?;
entity.entry_points().clone().take_entry_points()
self.context
.get_casper_vm_v1_entry_point(Key::contract_entity_key(*entity_hash))?
};
for entry_point in entry_points {
for entry_point in entry_points.take_entry_points() {
match entry_point.access() {
EntryPointAccess::Public | EntryPointAccess::Template => {
continue;
Expand Down
48 changes: 43 additions & 5 deletions execution_engine/src/runtime_context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ use casper_types::{
handle_stored_dictionary_value,
system::auction::EraInfo,
AccessRights, AddressableEntity, AddressableEntityHash, BlockTime, CLType, CLValue,
CLValueDictionary, ContextAccessRights, EntityAddr, EntryPointType, Gas, GrantedAccess, Key,
KeyTag, Motes, Package, PackageHash, Phase, ProtocolVersion, PublicKey, RuntimeArgs,
StoredValue, StoredValueTypeMismatch, SystemEntityRegistry, TransactionHash, Transfer, URef,
URefAddr, DICTIONARY_ITEM_KEY_MAX_LENGTH, KEY_HASH_LENGTH, U512,
CLValueDictionary, ContextAccessRights, EntityAddr, EntryPointAddr, EntryPointType,
EntryPointValue, EntryPoints, Gas, GrantedAccess, Key, KeyTag, Motes, Package, PackageHash,
Phase, ProtocolVersion, PublicKey, RuntimeArgs, StoredValue, StoredValueTypeMismatch,
SystemEntityRegistry, TransactionHash, Transfer, URef, URefAddr,
DICTIONARY_ITEM_KEY_MAX_LENGTH, KEY_HASH_LENGTH, U512,
};

use crate::{engine_state::EngineConfig, execution::ExecError};
Expand Down Expand Up @@ -419,6 +420,42 @@ where
.map_err(Into::into)
}

pub(crate) fn write_entry_points(
&mut self,
entity_addr: EntityAddr,
entry_points: EntryPoints,
) -> Result<(), ExecError> {
if entry_points.is_empty() {
return Ok(());
}

for entry_point in entry_points.take_entry_points() {
let entry_point_addr =
EntryPointAddr::new_v1_entry_point_addr(entity_addr, entry_point.name())?;
let entry_point_value =
StoredValue::EntryPoint(EntryPointValue::V1CasperVm(entry_point));
self.metered_write_gs_unsafe(Key::EntryPoint(entry_point_addr), entry_point_value)?;
}

Ok(())
}

pub(crate) fn get_casper_vm_v1_entry_point(
&mut self,
entity_key: Key,
) -> Result<EntryPoints, ExecError> {
let entity_addr = if let Key::AddressableEntity(entity_addr) = entity_key {
entity_addr
} else {
return Err(ExecError::UnexpectedKeyVariant(entity_key));
};

self.tracking_copy
.borrow_mut()
.get_v1_entry_points(entity_addr)
.map_err(Into::into)
}

#[cfg(test)]
pub(crate) fn get_entity(&self) -> AddressableEntity {
self.entity.clone()
Expand Down Expand Up @@ -676,7 +713,8 @@ where
| StoredValue::ContractWasm(_)
| StoredValue::MessageTopic(_)
| StoredValue::Message(_)
| StoredValue::Reservation(_) => Ok(()),
| StoredValue::Reservation(_)
| StoredValue::EntryPoint(_) => Ok(()),
}
}

Expand Down
7 changes: 3 additions & 4 deletions execution_engine/src/runtime_context/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use casper_types::{
execution::TransformKindV2,
system::{AUCTION, HANDLE_PAYMENT, MINT, STANDARD_PAYMENT},
AccessRights, AddressableEntity, AddressableEntityHash, BlockGlobalAddr, BlockTime,
ByteCodeHash, CLValue, ContextAccessRights, EntityAddr, EntityKind, EntryPointType,
EntryPoints, Gas, Key, PackageHash, Phase, ProtocolVersion, PublicKey, RuntimeArgs, SecretKey,
StoredValue, SystemEntityRegistry, Tagged, Timestamp, TransactionHash, TransactionV1Hash, URef,
ByteCodeHash, CLValue, ContextAccessRights, EntityAddr, EntityKind, EntryPointType, Gas, Key,
PackageHash, Phase, ProtocolVersion, PublicKey, RuntimeArgs, SecretKey, StoredValue,
SystemEntityRegistry, Tagged, Timestamp, TransactionHash, TransactionV1Hash, URef,
KEY_HASH_LENGTH, U256, U512,
};
use tempfile::TempDir;
Expand Down Expand Up @@ -65,7 +65,6 @@ fn new_addressable_entity_with_purse(
let entity = AddressableEntity::new(
PackageHash::default(),
ByteCodeHash::default(),
EntryPoints::new_with_default_entry_point(),
ProtocolVersion::V1_0_0,
URef::new(purse, AccessRights::READ_ADD_WRITE),
associated_keys,
Expand Down
21 changes: 18 additions & 3 deletions execution_engine_testing/test_support/src/wasm_test_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ use casper_types::{
},
AccessRights, AddressableEntity, AddressableEntityHash, AuctionCosts, BlockGlobalAddr,
BlockTime, ByteCode, ByteCodeAddr, ByteCodeHash, CLTyped, CLValue, Contract, Digest,
EntityAddr, EraId, Gas, HandlePaymentCosts, HoldBalanceHandling, InitiatorAddr, Key, KeyTag,
MintCosts, Motes, Package, PackageHash, Phase, ProtocolUpgradeConfig, ProtocolVersion,
PublicKey, RefundHandling, StoredValue, SystemEntityRegistry, TransactionHash,
EntityAddr, EntryPoints, EraId, Gas, HandlePaymentCosts, HoldBalanceHandling, InitiatorAddr,
Key, KeyTag, MintCosts, Motes, Package, PackageHash, Phase, ProtocolUpgradeConfig,
ProtocolVersion, PublicKey, RefundHandling, StoredValue, SystemEntityRegistry, TransactionHash,
TransactionV1Hash, URef, OS_PAGE_SIZE, U512,
};

Expand Down Expand Up @@ -1661,6 +1661,21 @@ where
reader.keys_with_prefix(&[tag as u8])
}

/// Gets all entry points for a given entity
pub fn get_entry_points(&self, entity_addr: EntityAddr) -> EntryPoints {
let state_root_hash = self.get_post_state_hash();

let mut tracking_copy = self
.data_access_layer
.tracking_copy(state_root_hash)
.unwrap()
.unwrap();

tracking_copy
.get_v1_entry_points(entity_addr)
.expect("must get entry points")
}

/// Gets a stored value from a contract's named keys.
pub fn get_value<T>(&mut self, entity_addr: EntityAddr, name: &str) -> T
where
Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"genesis_request": {
"protocol_version": "2.0.0"
},
"post_state_hash": "9e58f96c2051b314545821d2bec3e8ed7679b46f9664a97402affafd0e91bf73"
"post_state_hash": "142b11d6b28f64826957efb079aed265004964f6c0a70c1bbe813cb752918b9c"
}
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion execution_engine_testing/tests/fixtures/groups/state.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"genesis_request": {
"protocol_version": "2.0.0"
},
"post_state_hash": "373e18a37b361d454f61ed423fc128d7d7d5191e866639822996fa5915815ce2"
"post_state_hash": "f20f7ce0bb0b1f42605b58a488d87f0beaf17e6eeb6e63fafdcee1ea638e118f"
}
8 changes: 4 additions & 4 deletions execution_engine_testing/tests/src/test/explorer/faucet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,10 +926,10 @@ fn faucet_costs() {
// This test will fail if execution costs vary. The expected costs should not be updated
// without understanding why the cost has changed. If the costs do change, it should be
// reflected in the "Costs by Entry Point" section of the faucet crate's README.md.
const EXPECTED_FAUCET_INSTALL_COST: u64 = 89_201_674_240;
const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 111_263_840;
const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_750_259_320;
const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_619_720_120;
const EXPECTED_FAUCET_INSTALL_COST: u64 = 91_712_843_810;
const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 111_285_530;
const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_747_759_050;
const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_619_760_730;

let installer_account = AccountHash::new([1u8; 32]);
let user_account: AccountHash = AccountHash::new([2u8; 32]);
Expand Down
Loading

0 comments on commit 47cd7d3

Please sign in to comment.