Skip to content

Commit

Permalink
Merge #4376
Browse files Browse the repository at this point in the history
4376: Fix addressable entity request r=alsrdn a=alsrdn

Fix request for `AddressableEntity` when using `Key::Account`, `Key::Hash` and `Key::AddressableEntity`.

We now store an `AddressableEntity` record under `Key::AddressableEntity` instead of `Key::Hash`. Also, under `Key::Account` we store a CLValue containing a `Key::AddressableEntity` which can be then used to get the addressable entity.
When using `Key::Hash` we first try to get the addressable entity by running a query for `Key::AddressableEntity(PackageKindTag::SmartContract, contract_hash)`. If we can't find the entity under that key we try to read a `Contract` using the `Key::Hash`.


Co-authored-by: Alexandru Sardan <alexandru@casperlabs.io>
  • Loading branch information
casperlabs-bors-ng[bot] and Alexandru Sardan authored Oct 30, 2023
2 parents 949f0bb + 0b3c054 commit 797b823
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 43 deletions.
142 changes: 107 additions & 35 deletions node/src/components/contract_runtime/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@ use casper_storage::{
global_state::state::{lmdb::LmdbGlobalState, CommitProvider, StateProvider},
};
use casper_types::{
account::AccountHash,
bytesrepr::{self, ToBytes, U32_SERIALIZED_LENGTH},
execution::{Effects, ExecutionResult, ExecutionResultV2, Transform, TransformKind},
AddressableEntity, BlockV2, CLValue, DeployHash, Digest, EraEndV2, EraId, HashAddr, Key,
ProtocolVersion, PublicKey, StoredValue, U512,
AddressableEntity, AddressableEntityHash, BlockV2, CLValue, DeployHash, Digest, EraEndV2,
EraId, HashAddr, Key, ProtocolVersion, PublicKey, StoredValue, U512,
};

use crate::{
components::contract_runtime::{
error::BlockExecutionError, types::StepEffectsAndUpcomingEraValidators,
BlockAndExecutionResults, ExecutionPreState, Metrics, SpeculativeExecutionState,
APPROVALS_CHECKSUM_NAME, EXECUTION_RESULTS_CHECKSUM_NAME,
BlockAndExecutionResults, ExecutionPreState, Metrics, PackageKindTag,
SpeculativeExecutionState, APPROVALS_CHECKSUM_NAME, EXECUTION_RESULTS_CHECKSUM_NAME,
},
types::{self, ApprovalsHashes, Chunkable, ExecutableBlock, InternalEraReport},
utils::fetch_id,
Expand Down Expand Up @@ -590,38 +591,97 @@ where
S: StateProvider + CommitProvider,
S::Error: Into<execution::Error>,
{
let account_key = match key {
Key::Hash(hash_addr) => {
return get_addressable_entity_under_hash(engine_state, state_root_hash, hash_addr)
match key {
Key::AddressableEntity(package_kind_tag, entity_addr) => {
get_addressable_entity_under_entity_hash(
engine_state,
state_root_hash,
package_kind_tag,
entity_addr.into(),
)
}
Key::Account(account_hash) => {
get_addressable_entity_under_account_hash(engine_state, state_root_hash, account_hash)
}
Key::Hash(contract_hash) => {
get_addressable_entity_under_contract_hash(engine_state, state_root_hash, contract_hash)
}
account_key @ Key::Account(_) => account_key,
_ => {
warn!(%key, "expected a Key::Hash or Key::Account");
warn!(%key, "expected a Key::AddressableEntity, Key::Account, Key::Hash");
None
}
}
}

fn get_addressable_entity_under_entity_hash<S>(
engine_state: &EngineState<S>,
state_root_hash: Digest,
package_kind_tag: PackageKindTag,
entity_hash: AddressableEntityHash,
) -> Option<AddressableEntity>
where
S: StateProvider + CommitProvider,
S::Error: Into<execution::Error>,
{
let key = Key::addressable_entity_key(package_kind_tag, entity_hash);
let query_request = QueryRequest::new(state_root_hash, key, vec![]);
let value = match engine_state.run_query(query_request) {
Ok(QueryResult::Success { value, .. }) => *value,
Ok(result) => {
debug!(?result, %key, "expected to find addressable entity");
return None;
}
Err(error) => {
warn!(%error, %key, "failed querying for addressable entity");
return None;
}
};
match value {
StoredValue::AddressableEntity(addressable_entity) => Some(addressable_entity),
_ => {
debug!(type_name = %value.type_name(), %key, "expected an AddressableEntity");
None
}
}
}

fn get_addressable_entity_under_account_hash<S>(
engine_state: &EngineState<S>,
state_root_hash: Digest,
account_hash: AccountHash,
) -> Option<AddressableEntity>
where
S: StateProvider + CommitProvider,
S::Error: Into<execution::Error>,
{
let account_key = Key::Account(account_hash);
let query_request = QueryRequest::new(state_root_hash, account_key, vec![]);
let value = match engine_state.run_query(query_request) {
Ok(QueryResult::Success { value, .. }) => *value,
Ok(result) => {
debug!(?result, %key, "expected to find stored value under account hash");
debug!(?result, %account_key, "expected to find stored value under account hash");
return None;
}
Err(error) => {
warn!(%error, %key, "failed querying for stored value under account hash");
warn!(%error, %account_key, "failed querying for stored value under account hash");
return None;
}
};
match value {
StoredValue::CLValue(cl_value) => match cl_value.into_t::<Key>() {
Ok(Key::Hash(hash_addr)) => {
get_addressable_entity_under_hash(engine_state, state_root_hash, hash_addr)
Ok(Key::AddressableEntity(package_kind_tag, entity_addr)) => {
get_addressable_entity_under_entity_hash(
engine_state,
state_root_hash,
package_kind_tag,
entity_addr.into(),
)
}
Ok(invalid_key) => {
warn!(
%account_key,
%invalid_key,
"expected a Key::Hash to be stored under account hash"
"expected a Key::AddressableEntity to be stored under account hash"
);
None
}
Expand All @@ -642,35 +702,47 @@ where
}
}

fn get_addressable_entity_under_hash<S>(
fn get_addressable_entity_under_contract_hash<S>(
engine_state: &EngineState<S>,
state_root_hash: Digest,
hash_addr: HashAddr,
contract_hash: HashAddr,
) -> Option<AddressableEntity>
where
S: StateProvider + CommitProvider,
S::Error: Into<execution::Error>,
{
let key = Key::Hash(hash_addr);
let query_request = QueryRequest::new(state_root_hash, key, vec![]);
let value = match engine_state.run_query(query_request) {
Ok(QueryResult::Success { value, .. }) => *value,
Ok(result) => {
debug!(?result, %key, "expected to find addressable entity");
return None;
}
Err(error) => {
warn!(%error, %key, "failed querying for addressable entity");
return None;
}
};
match value {
StoredValue::AddressableEntity(addressable_entity) => Some(addressable_entity),
_ => {
debug!(type_name = %value.type_name(), %key, "expected an AddressableEntity");
None
// First try with an `AddressableEntityHash` derived from the contract hash.
get_addressable_entity_under_entity_hash(
engine_state,
state_root_hash,
PackageKindTag::SmartContract,
contract_hash.into(),
).or_else(|| {
// Didn't work; the contract was either not migrated yet or the `AddressableEntity`
// record was not available at this state root hash. Try to query with a
// contract key next.
let contract_key = Key::Hash(contract_hash);
let query_request = QueryRequest::new(state_root_hash, contract_key, vec![]);
let value = match engine_state.run_query(query_request) {
Ok(QueryResult::Success { value, .. }) => *value,
Ok(result) => {
debug!(?result, %contract_key, "expected to find a stored value for a contract hash");
return None;
}
Err(error) => {
warn!(%error, %contract_key, "failed querying for a contract hash");
return None;
}
};

match value {
StoredValue::Contract(contract) => Some(contract.into()),
_ => {
debug!(type_name = %value.type_name(), ?contract_hash, "expected a Contract");
None
}
}
}
})
}

#[cfg(test)]
Expand Down
14 changes: 7 additions & 7 deletions node/src/components/transaction_acceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use tracing::{debug, error, trace};

use casper_execution_engine::engine_state::{BalanceRequest, MAX_PAYMENT};
use casper_types::{
account::AccountHash, addressable_entity::AddressableEntity, package::Package,
system::auction::ARG_AMOUNT, AddressableEntityHash, BlockHeader, Chainspec, DirectCallV1,
EntityIdentifier, EntityVersion, EntityVersionKey, ExecutableDeployItem,
account::AccountHash, addressable_entity::AddressableEntity, contracts::ContractHash,
package::Package, system::auction::ARG_AMOUNT, AddressableEntityHash, BlockHeader, Chainspec,
DirectCallV1, EntityIdentifier, EntityVersion, EntityVersionKey, ExecutableDeployItem,
ExecutableDeployItemIdentifier, Key, PackageHash, PackageIdentifier, ProtocolVersion,
Transaction, TransactionConfig, TransactionV1Kind, UserlandTransactionV1, U512,
};
Expand Down Expand Up @@ -313,7 +313,7 @@ impl TransactionAcceptor {
ExecutableDeployItemIdentifier::AddressableEntity(EntityIdentifier::Hash(
contract_hash,
)) => {
let query_key = Key::contract_entity_key(contract_hash);
let query_key = Key::from(ContractHash::new(contract_hash.value()));
effect_builder
.get_addressable_entity(*block_header.state_root_hash(), query_key)
.event(move |maybe_contract| Event::GetContractResult {
Expand Down Expand Up @@ -418,7 +418,7 @@ impl TransactionAcceptor {
ExecutableDeployItemIdentifier::AddressableEntity(EntityIdentifier::Hash(
entity_hash,
)) => {
let key = Key::contract_entity_key(entity_hash);
let key = Key::from(ContractHash::new(entity_hash.value()));
effect_builder
.get_addressable_entity(*block_header.state_root_hash(), key)
.event(move |maybe_contract| Event::GetContractResult {
Expand Down Expand Up @@ -497,7 +497,7 @@ impl TransactionAcceptor {

match next_step {
NextStep::GetContract(contract_hash) => {
let key = Key::contract_entity_key(contract_hash);
let key = Key::from(ContractHash::new(contract_hash.value()));
effect_builder
.get_addressable_entity(*block_header.state_root_hash(), key)
.event(move |maybe_contract| Event::GetContractResult {
Expand Down Expand Up @@ -613,7 +613,7 @@ impl TransactionAcceptor {
EntityVersionKey::new(self.protocol_version.value().major, contract_version);
match package.lookup_entity_hash(contract_version_key) {
Some(&contract_hash) => {
let key = Key::contract_entity_key(contract_hash);
let key = Key::from(ContractHash::new(contract_hash.value()));
effect_builder
.get_addressable_entity(*block_header.state_root_hash(), key)
.event(move |maybe_contract| Event::GetContractResult {
Expand Down
2 changes: 1 addition & 1 deletion node/src/components/transaction_acceptor/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ impl reactor::Reactor for Reactor {
} else if let Key::Account(account_hash) = key {
let account = create_account(account_hash, self.test_scenario);
Some(AddressableEntity::from(account))
} else if let Key::AddressableEntity(..) = key {
} else if let Key::Hash(..) = key {
match self.test_scenario {
TestScenario::FromPeerCustomPaymentContract(
ContractScenario::MissingContractAtHash,
Expand Down

0 comments on commit 797b823

Please sign in to comment.