linera-io/linera-protocol · error
SetRpcEndpoint requires an authenticated signer
Error message
SetRpcEndpoint requires an authenticated signer
What it means
SetRpcEndpoint is owner-only: the contract expects runtime.authenticated_owner() to return Some, i.e. the executing transaction must carry the bridge-chain owner's signature. When it panics, the whole transaction aborts and the previously stored rpc_endpoint is left unchanged. Note that even after passing this gate, validate_rpc_endpoint will dial the endpoint and abort on failure.
Source
Thrown at linera-bridge/contracts/evm-bridge/src/contract.rs:105
.verified_block_hashes
.insert(&block_hash)
.expect("failed to insert verified block hash");
}
}
BridgeOperation::RegisterFungibleBridge { address } => {
self.runtime
.authenticated_owner()
.expect("RegisterFungibleBridge requires an authenticated signer");
assert!(
self.state.bridge_contract_address.get().is_none(),
"bridge contract address is already registered and cannot be changed"
);
self.state.bridge_contract_address.set(Some(address));
}
BridgeOperation::SetRpcEndpoint { rpc_endpoint } => {
self.runtime
.authenticated_owner()
.expect("SetRpcEndpoint requires an authenticated signer");
self.validate_rpc_endpoint(&rpc_endpoint).await;
self.state.rpc_endpoint.set(rpc_endpoint);
}
BridgeOperation::Burn { amount, evm_target } => {
self.initiate_burn(amount, evm_target);
}
}
}
async fn execute_message(&mut self, message: BridgeMessage) {
match message {
BridgeMessage::Burn { amount, evm_target } => {
// A bouncing delivery is a no-op: the funding transfer is part
// of the same outgoing bundle and bounces on its own, refunding
// the user on their chain via wrapped-fungible's Credit handler.
let is_bouncing = self
.runtime
.message_is_bouncing()View on GitHub (pinned to 6c226ddcb3)
Solutions
- Sign and submit SetRpcEndpoint with the bridge chain owner's key
- Confirm the target chain is the bridge chain and the wallet actually owns it (linera wallet show)
- Pre-flight the new endpoint's chain ID (see validate_rpc_endpoint) so the signed transaction does not abort after the auth check
- In your own contract builds, turn the expect into an assert! for a clearer rejection
Example fix
// before
self.runtime
.authenticated_owner()
.expect("SetRpcEndpoint requires an authenticated signer");
// after
assert!(
self.runtime.authenticated_owner().is_some(),
"SetRpcEndpoint requires an authenticated signer"
);
// Caller-side: ensure the submission client signs with the bridge chain
// owner key, e.g. linera process-and-transfer --signer <owner-key> ... Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight both gates before spending a transaction:
// 1) signer must be the bridge chain owner
assert_eq!(wallet.owner_of(bridge_chain_id), Some(signer.public()));
// 2) endpoint must answer with the configured chain ID
let id = http_post_json(&rpc_endpoint, eth_chain_id_request()).await?;
assert_eq!(id, format!("0x{source_chain_id:x}"));
client.submit(bridge_chain_id, BridgeOperation::SetRpcEndpoint { rpc_endpoint }); Try / catch
// The panic aborts the SetRpcEndpoint transaction atomically; catch nothing, // instead inspect the block's rejected-transaction error, fix signer or // endpoint, and resubmit. State (old endpoint) is unchanged.
Prevention
- Keep a runbook mapping each bridge chain to its owner key
- Rotate keys through a documented handover that updates deployment automation in the same change
- Pre-flight eth_chainId from the machine that will submit the operation
When it happens
Trigger: Submitting SetRpcEndpoint signed by a non-owner key; executing it via a cross-application session with no authenticated signer; running an ops script that authenticates with a read-only or rotated key after the owner key changed.
Common situations: Rotating the bridge owner key and forgetting to update deployment automation; pointing an ops pipeline at the bridge chain with a watcher wallet instead of the owner wallet; testnets where chains are created by one account and operated by another.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- RegisterFungibleBridge requires an authenticated signer
- failed to query chain ID from RPC endpoint
- Burn requires an authenticated signer
- invalid block header RLP
- receipt inclusion proof failed
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/e5e821565052e83f.
Report an issue: GitHub.