Skip to content

Commit 58afb87

Browse files
authored
Fix authenticated signer syscall and remove the offending field (#4392)
## Motivation Fix authenticated signer. ## Proposal As pointed out in #4374, we were using the transaction instead of the last application on the calling stack, effectively ignoring whether calls were "authenticated" or not. * Fix the bug * Remove the field that caused the confusion in the first place ## Test Plan CI + new unit test I verified that the new unit test fails before the fix. ## Release Plan - These changes should be backported to the latest `devnet` branch, then - be released in a new SDK, - be released in a validator hotfix.
1 parent 41874af commit 58afb87

File tree

3 files changed

+72
-11
lines changed

3 files changed

+72
-11
lines changed

linera-execution/src/runtime.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,6 @@ pub struct SyncRuntimeInternal<UserInstance: WithContext> {
8787
height: BlockHeight,
8888
/// The current consensus round. Only available during block validation in multi-leader rounds.
8989
round: Option<u32>,
90-
/// The authenticated signer of the operation or message, if any.
91-
#[debug(skip_if = Option::is_none)]
92-
authenticated_signer: Option<AccountOwner>,
9390
/// The current message being executed, if there is one.
9491
#[debug(skip_if = Option::is_none)]
9592
executing_message: Option<ExecutingMessage>,
@@ -311,7 +308,6 @@ impl<UserInstance: WithContext> SyncRuntimeInternal<UserInstance> {
311308
chain_id: ChainId,
312309
height: BlockHeight,
313310
round: Option<u32>,
314-
authenticated_signer: Option<AccountOwner>,
315311
executing_message: Option<ExecutingMessage>,
316312
execution_state_sender: ExecutionStateSender,
317313
deadline: Option<Instant>,
@@ -324,7 +320,6 @@ impl<UserInstance: WithContext> SyncRuntimeInternal<UserInstance> {
324320
chain_id,
325321
height,
326322
round,
327-
authenticated_signer,
328323
executing_message,
329324
execution_state_sender,
330325
is_finalizing: false,
@@ -1008,7 +1003,6 @@ impl ContractSyncRuntime {
10081003
chain_id,
10091004
action.height(),
10101005
action.round(),
1011-
action.signer(),
10121006
if let UserAction::Message(context, _) = action {
10131007
Some(context.into())
10141008
} else {
@@ -1085,7 +1079,6 @@ impl ContractSyncRuntimeHandle {
10851079

10861080
{
10871081
let runtime = self.inner();
1088-
assert_eq!(runtime.authenticated_signer, action.signer());
10891082
assert_eq!(runtime.chain_id, chain_id);
10901083
assert_eq!(runtime.height, action.height());
10911084
}
@@ -1171,7 +1164,8 @@ impl ContractSyncRuntimeHandle {
11711164

11721165
impl ContractRuntime for ContractSyncRuntimeHandle {
11731166
fn authenticated_signer(&mut self) -> Result<Option<AccountOwner>, ExecutionError> {
1174-
Ok(self.inner().authenticated_signer)
1167+
let this = self.inner();
1168+
Ok(this.current_application().signer)
11751169
}
11761170

11771171
fn message_is_bouncing(&mut self) -> Result<Option<bool>, ExecutionError> {
@@ -1686,7 +1680,6 @@ impl ServiceSyncRuntime {
16861680
context.next_block_height,
16871681
None,
16881682
None,
1689-
None,
16901683
execution_state_sender,
16911684
deadline,
16921685
None,

linera-execution/src/unit_tests/runtime_tests.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ where
180180
BlockHeight(0),
181181
Some(0),
182182
None,
183-
None,
184183
execution_state_sender,
185184
None,
186185
None,

linera-execution/tests/contract_runtime_apis.rs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::{
1010

1111
use assert_matches::assert_matches;
1212
use linera_base::{
13-
crypto::CryptoHash,
13+
crypto::{AccountPublicKey, CryptoHash},
1414
data_types::{
1515
Amount, ApplicationDescription, ApplicationPermissions, Blob, BlockHeight, Bytecode,
1616
CompressedBytecode, OracleResponse,
@@ -1056,3 +1056,72 @@ async fn test_publish_module_different_bytecode() -> anyhow::Result<()> {
10561056

10571057
Ok(())
10581058
}
1059+
1060+
#[test_log::test(tokio::test)]
1061+
async fn test_callee_api_calls() -> anyhow::Result<()> {
1062+
let (state, chain_id) = SystemExecutionState::dummy_chain_state(0);
1063+
let mut view = state.into_view().await;
1064+
1065+
let (caller_id, caller_application, caller_blobs) = view.register_mock_application(0).await?;
1066+
let (target_id, target_application, target_blobs) = view.register_mock_application(1).await?;
1067+
1068+
let owner = AccountOwner::from(AccountPublicKey::test_key(0));
1069+
let dummy_operation = vec![1];
1070+
1071+
caller_application.expect_call({
1072+
let dummy_operation = dummy_operation.clone();
1073+
ExpectedCall::execute_operation(move |runtime, operation| {
1074+
assert_eq!(operation, dummy_operation);
1075+
1076+
// Call the target application with authentication.
1077+
let response =
1078+
runtime.try_call_application(/* authenticated */ true, target_id, vec![])?;
1079+
assert!(response.is_empty());
1080+
1081+
// Call the target application without authentication.
1082+
let response =
1083+
runtime.try_call_application(/* authenticated */ false, target_id, vec![])?;
1084+
assert!(response.is_empty());
1085+
1086+
Ok(vec![])
1087+
})
1088+
});
1089+
1090+
target_application.expect_call(ExpectedCall::execute_operation(move |runtime, argument| {
1091+
assert!(argument.is_empty());
1092+
assert_eq!(runtime.authenticated_signer().unwrap(), Some(owner));
1093+
assert_eq!(runtime.authenticated_caller_id().unwrap(), Some(caller_id));
1094+
Ok(vec![])
1095+
}));
1096+
target_application.expect_call(ExpectedCall::execute_operation(move |runtime, argument| {
1097+
assert!(argument.is_empty());
1098+
assert_eq!(runtime.authenticated_signer().unwrap(), None);
1099+
assert_eq!(runtime.authenticated_caller_id().unwrap(), None);
1100+
Ok(vec![])
1101+
}));
1102+
1103+
target_application.expect_call(ExpectedCall::default_finalize());
1104+
caller_application.expect_call(ExpectedCall::default_finalize());
1105+
1106+
let context = OperationContext {
1107+
authenticated_signer: Some(owner),
1108+
..create_dummy_operation_context(chain_id)
1109+
};
1110+
let mut controller = ResourceController::default();
1111+
let mut txn_tracker =
1112+
TransactionTracker::new_replaying_blobs(caller_blobs.iter().chain(&target_blobs));
1113+
view.execute_operation(
1114+
context,
1115+
Operation::User {
1116+
application_id: caller_id,
1117+
bytes: dummy_operation.clone(),
1118+
},
1119+
&mut txn_tracker,
1120+
&mut controller,
1121+
)
1122+
.await
1123+
.unwrap();
1124+
let txn_outcome = txn_tracker.into_outcome().unwrap();
1125+
assert!(txn_outcome.outgoing_messages.is_empty());
1126+
Ok(())
1127+
}

0 commit comments

Comments
 (0)