Skip to content

Commit 538cb2e

Browse files
committed
fixup! feat(truapi-server): add platform runtime and host bridge
1 parent fd73265 commit 538cb2e

1 file changed

Lines changed: 127 additions & 4 deletions

File tree

rust/crates/truapi-server/src/runtime.rs

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -645,13 +645,15 @@ impl PlatformRuntimeHost {
645645
&self,
646646
session: &SessionInfo,
647647
signer: &str,
648-
) -> Result<(), v01::HostSignPayloadError> {
648+
) -> Result<[u8; 32], v01::HostSignPayloadError> {
649649
let public_key = self
650650
.legacy_slot_zero_public_key(session)
651651
.map_err(|reason| v01::HostSignPayloadError::Unknown { reason })?;
652652
let expected = product_public_key_to_address(public_key);
653-
if expected == signer {
654-
Ok(())
653+
if expected == signer
654+
|| parse_legacy_signer_hex(signer).is_some_and(|key| key == public_key)
655+
{
656+
Ok(public_key)
655657
} else {
656658
Err(v01::HostSignPayloadError::Unknown {
657659
reason: "Account can't be derived from product account id".to_string(),
@@ -677,6 +679,17 @@ impl PlatformRuntimeHost {
677679
}
678680
}
679681

682+
fn parse_legacy_signer_hex(signer: &str) -> Option<[u8; 32]> {
683+
let raw = signer
684+
.strip_prefix("0x")
685+
.or_else(|| signer.strip_prefix("0X"))
686+
.unwrap_or(signer);
687+
if raw.len() != 64 {
688+
return None;
689+
}
690+
hex::decode(raw).ok()?.try_into().ok()
691+
}
692+
680693
/// Adapter from `truapi_platform::ChainProvider` into the
681694
/// [`RuntimeChainProvider`] surface the chain runtime expects.
682695
/// Reuses the platform-supplied json-rpc connection and converts the
@@ -3012,11 +3025,60 @@ mod tests {
30123025
crate::host_logic::sso::messages::RemoteMessageV1::SignRequest(request)
30133026
) if matches!(
30143027
request.as_ref(),
3015-
crate::host_logic::sso::messages::SigningRequest::Raw(_)
3028+
crate::host_logic::sso::messages::SigningRequest::Raw(raw)
3029+
if raw.product_account_id == account_id("myapp.dot", 0)
3030+
&& matches!(
3031+
&raw.data,
3032+
crate::host_logic::sso::messages::SigningRawPayload::Bytes(bytes)
3033+
if bytes == b"hello"
3034+
)
30163035
)
30173036
));
30183037
}
30193038

3039+
#[test]
3040+
fn legacy_sign_raw_accepts_derived_hex_then_returns_sso_response() {
3041+
let session = sso_session_info();
3042+
let signer = derive_product_public_key(session.public_key, "myapp.dot", 0).unwrap();
3043+
let platform = Arc::new(StubPlatform {
3044+
sign_raw_confirmed: true,
3045+
rpc_responses: sso_success_responses(
3046+
&session,
3047+
"legacy-sign-raw-hex-1",
3048+
sign_response_message("legacy-sign-raw-hex-1", vec![8, 8], None),
3049+
),
3050+
..Default::default()
3051+
});
3052+
let host = PlatformRuntimeHost::new(
3053+
platform.clone(),
3054+
runtime_config("myapp.dot"),
3055+
test_spawner(),
3056+
);
3057+
host.session_state().set_session(session.clone());
3058+
let cx = CallContext::with_request_id("legacy-sign-raw-hex-1".to_string());
3059+
let request =
3060+
HostSignRawWithLegacyAccountRequest::V1(v01::HostSignRawWithLegacyAccountRequest {
3061+
signer: format!("0x{}", hex::encode(signer)),
3062+
payload: raw_payload(),
3063+
});
3064+
let response =
3065+
futures::executor::block_on(host.sign_raw_with_legacy_account(&cx, request)).unwrap();
3066+
let HostSignRawWithLegacyAccountResponse::V1(inner) = response;
3067+
assert_eq!(inner.signature, vec![8, 8]);
3068+
3069+
let message = submitted_remote_message(&platform, &session);
3070+
let crate::host_logic::sso::messages::RemoteMessageData::V1(
3071+
crate::host_logic::sso::messages::RemoteMessageV1::SignRequest(request),
3072+
) = message.data
3073+
else {
3074+
panic!("expected raw signing request");
3075+
};
3076+
let crate::host_logic::sso::messages::SigningRequest::Raw(request) = *request else {
3077+
panic!("expected raw signing request");
3078+
};
3079+
assert_eq!(request.product_account_id, account_id("myapp.dot", 0));
3080+
}
3081+
30203082
#[test]
30213083
fn legacy_create_transaction_rejects_raw_key_mismatch() {
30223084
let host =
@@ -3042,6 +3104,67 @@ mod tests {
30423104
}
30433105
}
30443106

3107+
#[test]
3108+
fn legacy_create_transaction_accepts_derived_key_then_returns_sso_response() {
3109+
let session = sso_session_info();
3110+
let signer = derive_product_public_key(session.public_key, "myapp.dot", 0).unwrap();
3111+
let platform = Arc::new(StubPlatform {
3112+
create_transaction_confirmed: true,
3113+
rpc_responses: sso_success_responses(
3114+
&session,
3115+
"legacy-create-tx-1",
3116+
crate::host_logic::sso::messages::RemoteMessage {
3117+
message_id: "wallet-legacy-create-tx-1".to_string(),
3118+
data: crate::host_logic::sso::messages::RemoteMessageData::V1(
3119+
crate::host_logic::sso::messages::RemoteMessageV1::CreateTransactionResponse(
3120+
crate::host_logic::sso::messages::CreateTransactionResponse {
3121+
responding_to: "legacy-create-tx-1".to_string(),
3122+
signed_transaction: Ok(vec![0xca, 0xfe]),
3123+
},
3124+
),
3125+
),
3126+
},
3127+
),
3128+
..Default::default()
3129+
});
3130+
let host = PlatformRuntimeHost::new(
3131+
platform.clone(),
3132+
runtime_config("myapp.dot"),
3133+
test_spawner(),
3134+
);
3135+
host.session_state().set_session(session.clone());
3136+
let cx = CallContext::with_request_id("legacy-create-tx-1".to_string());
3137+
let request =
3138+
HostCreateTransactionWithLegacyAccountRequest::V1(v01::LegacyAccountTxPayload {
3139+
signer,
3140+
genesis_hash: [1; 32],
3141+
call_data: vec![0],
3142+
extensions: vec![],
3143+
tx_ext_version: 0,
3144+
});
3145+
3146+
let response =
3147+
futures::executor::block_on(host.create_transaction_with_legacy_account(&cx, request))
3148+
.unwrap();
3149+
3150+
let HostCreateTransactionWithLegacyAccountResponse::V1(inner) = response;
3151+
assert_eq!(inner.transaction, vec![0xca, 0xfe]);
3152+
let message = submitted_remote_message(&platform, &session);
3153+
let crate::host_logic::sso::messages::RemoteMessageData::V1(
3154+
crate::host_logic::sso::messages::RemoteMessageV1::CreateTransactionRequest(request),
3155+
) = message.data
3156+
else {
3157+
panic!("expected product transaction request");
3158+
};
3159+
let crate::host_logic::sso::messages::CreateTransactionPayload::V1(payload) =
3160+
request.payload;
3161+
assert_eq!(payload.signer, account_id("myapp.dot", 0));
3162+
assert_eq!(
3163+
signer,
3164+
derive_product_public_key(session.public_key, "myapp.dot", 0).unwrap()
3165+
);
3166+
}
3167+
30453168
#[test]
30463169
fn create_transaction_rejects_invalid_product_account() {
30473170
let host =

0 commit comments

Comments
 (0)