Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion EVM.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,12 @@ a raw signed RLP blob. The EVM transaction is stored as:
- Ethereum signed transaction hash: `hash`.
- Exactly one Casper `Approval` containing the Ethereum secp256k1 signature.

The generic transaction initiator is not stored as another EVM transaction
field. `EvmTransaction::initiator_addr()` derives
`InitiatorAddr::Eoa(transaction.from())` on demand. This keeps the 20-byte EVM
identity intact and avoids requiring callers such as sidecar's `eth_call` path
to fabricate a Casper `AccountHash` for an Ethereum address.

`evm::Hash`, `evm::Topic`, and `evm::TransactionHash` are `Digest`-backed
wrappers, but their constructors preserve the supplied 32 bytes as raw
Ethereum values. They do not hash the bytes again. `evm::Hash` is used for
Expand Down Expand Up @@ -374,7 +380,7 @@ meta_transaction = MetaTransaction::from_transaction(stored_transaction, ...)
Common metadata such as hash, authorization keys, size estimate, gas limit, and
cost is derived directly from `Transaction`. For EVM:

- the initiator is the EVM sender address, `transaction.from()`,
- the initiator is `InitiatorAddr::Eoa(transaction.from())`, derived on demand,
- the transaction lane is currently the last configured Wasm lane,
- the gas limit is the Ethereum transaction gas limit,
- the maximum cost is
Expand Down
14 changes: 14 additions & 0 deletions binary_port/src/error_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,9 @@ pub enum ErrorCode {
/// EVM transaction nonce does not match the account nonce.
#[error("the EVM transaction nonce does not match the account nonce")]
InvalidTransactionEvmInvalidNonce = 119,
/// EOA initiators are not valid for V1 transactions.
#[error("invalid initiator address for Transaction::V1")]
InvalidTransactionInvalidInitiatorAddr = 120,
}

impl TryFrom<u16> for ErrorCode {
Expand Down Expand Up @@ -481,6 +484,9 @@ impl From<InvalidTransactionV1> for ErrorCode {
}
InvalidTransactionV1::InvalidBodyHash => ErrorCode::InvalidTransactionBodyHash,
InvalidTransactionV1::InvalidTransactionHash => ErrorCode::InvalidTransactionHash,
InvalidTransactionV1::InvalidInitiatorAddr => {
ErrorCode::InvalidTransactionInvalidInitiatorAddr
}
InvalidTransactionV1::EmptyApprovals => ErrorCode::InvalidTransactionEmptyApprovals,
InvalidTransactionV1::InvalidApproval { .. } => {
ErrorCode::InvalidTransactionInvalidApproval
Expand Down Expand Up @@ -642,6 +648,14 @@ mod tests {
);
}

#[test]
fn invalid_v1_eoa_initiator_has_specific_error_code() {
let code = ErrorCode::from(InvalidTransactionV1::InvalidInitiatorAddr);

assert_eq!(code, ErrorCode::InvalidTransactionInvalidInitiatorAddr);
assert_eq!(code as u16, 120);
}

#[test]
fn try_from_decoded_all_variants() {
for variant in ErrorCode::iter() {
Expand Down
14 changes: 12 additions & 2 deletions execution_engine/src/engine_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ impl ExecutionEngineV1 {
// A good deal of effort has been put into removing all such behaviors; please do not
// come along and start adding it back.

let account_hash = initiator_addr.account_hash();
let Some(account_hash) = initiator_addr.account_hash() else {
return WasmV1Result::precondition_failure(
gas_limit,
Error::TrackingCopy(TrackingCopyError::Authorization),
);
};
Comment on lines +79 to +84

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good thinking. Auth error is the right call.

let protocol_version = self.config.protocol_version();
let state_hash = block_info.state_hash;
let tc = match state_provider.tracking_copy(state_hash) {
Expand Down Expand Up @@ -155,7 +160,12 @@ impl ExecutionEngineV1 {
// A good deal of effort has been put into removing all such behaviors; please do not
// come along and start adding it back.

let account_hash = initiator_addr.account_hash();
let Some(account_hash) = initiator_addr.account_hash() else {
return WasmV1Result::precondition_failure(
gas_limit,
Error::TrackingCopy(TrackingCopyError::Authorization),
);
};
let protocol_version = self.config.protocol_version();
let tc = Rc::new(RefCell::new(tracking_copy));
let (runtime_footprint, entity_addr) = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,11 @@ impl TransferRequestBuilder {
/// authorization keys.
pub fn with_initiator<T: Into<InitiatorAddr>>(mut self, initiator: T) -> Self {
self.initiator = initiator.into();
let _ = self
.authorization_keys
.insert(self.initiator.account_hash());
let _ = self.authorization_keys.insert(
self.initiator
.account_hash()
.expect("test transfer initiator must be a Casper account"),
);
self
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,11 @@ where
.expect("builder must have a post-state hash");

let transaction_hash = TransactionHash::V1(TransactionV1Hash::default());
let authorization_keys = BTreeSet::from_iter(iter::once(initiator.account_hash()));
let authorization_keys = BTreeSet::from_iter(iter::once(
initiator
.account_hash()
.expect("test bidding initiator must be a Casper account"),
));

let config = &self.chainspec;
let fee_handling = config.core_config.fee_handling;
Expand Down
Loading
Loading