use casper_types::{
bytesrepr::Bytes,
contracts::{NamedKeys, ProtocolVersionMajor},
AddressableEntityHash, EntityVersion, Key, PackageHash, TransactionInvocationTarget,
};
use super::{wasm_v1::SessionKind, Error, ExecutableItem};
use crate::execution::ExecError;
#[derive(Clone, Debug)]
pub(crate) enum ExecutionKind<'a> {
Standard(&'a Bytes),
InstallerUpgrader(&'a Bytes),
Stored {
entity_hash: AddressableEntityHash,
entry_point: String,
},
Deploy(&'a Bytes),
VersionedCall {
package_hash: PackageHash,
entity_version: Option<EntityVersion>,
protocol_version_major: Option<ProtocolVersionMajor>,
entry_point: String,
},
}
impl<'a> ExecutionKind<'a> {
pub(crate) fn new(
named_keys: &NamedKeys,
executable_item: &'a ExecutableItem,
entry_point: String,
) -> Result<Self, Error> {
match executable_item {
ExecutableItem::Invocation(target) => {
Self::new_direct_invocation(named_keys, target, entry_point)
}
ExecutableItem::PaymentBytes(module_bytes)
| ExecutableItem::SessionBytes {
kind: SessionKind::GenericBytecode,
module_bytes,
} => Ok(ExecutionKind::Standard(module_bytes)),
ExecutableItem::SessionBytes {
kind: SessionKind::InstallUpgradeBytecode,
module_bytes,
} => Ok(ExecutionKind::InstallerUpgrader(module_bytes)),
ExecutableItem::Deploy(module_bytes) => Ok(ExecutionKind::Deploy(module_bytes)),
}
}
fn new_direct_invocation(
named_keys: &NamedKeys,
target: &TransactionInvocationTarget,
entry_point: String,
) -> Result<Self, Error> {
let entity_hash = match target {
TransactionInvocationTarget::ByHash(addr) => AddressableEntityHash::new(*addr),
TransactionInvocationTarget::ByName(alias) => {
let entity_key = named_keys
.get(alias)
.ok_or_else(|| Error::Exec(ExecError::NamedKeyNotFound(alias.clone())))?;
match entity_key {
Key::Hash(hash) => AddressableEntityHash::new(*hash),
Key::AddressableEntity(entity_addr) => {
AddressableEntityHash::new(entity_addr.value())
}
_ => return Err(Error::InvalidKeyVariant(*entity_key)),
}
}
TransactionInvocationTarget::ByPackageHash {
addr,
version,
protocol_version_major,
} => {
let package_hash = PackageHash::from(*addr);
return Ok(Self::VersionedCall {
package_hash,
entity_version: *version,
protocol_version_major: *protocol_version_major,
entry_point,
});
}
TransactionInvocationTarget::ByPackageName {
name,
version,
protocol_version_major,
} => {
let package_key = named_keys
.get(name)
.ok_or_else(|| Error::Exec(ExecError::NamedKeyNotFound(name.to_string())))?;
let package_hash = match package_key {
Key::Hash(hash) | Key::SmartContract(hash) => PackageHash::new(*hash),
_ => return Err(Error::InvalidKeyVariant(*package_key)),
};
return Ok(Self::VersionedCall {
package_hash,
entity_version: *version,
protocol_version_major: *protocol_version_major,
entry_point,
});
}
};
Ok(ExecutionKind::Stored {
entity_hash,
entry_point,
})
}
}