Skip to content

Commit 63dbf07

Browse files
authored
feat: replace attested bytes with typed MessageOrigin in delegate API (#61)
* feat: replace attested bytes with typed MessageOrigin in delegate API Replace the raw `attested: Option<&'static [u8]>` parameter in DelegateInterface::process() with `origin: Option<MessageOrigin>`, where MessageOrigin::WebApp(ContractInstanceId) identifies the originating web application. Also removes the `app` field from ApplicationMessage — the origin is now conveyed through the process() parameter rather than being duplicated on every message. Closes #1498 * build: bump version to 0.3.0 for breaking API changes Breaking changes in this release: - DelegateInterface::process: attested → origin: Option<MessageOrigin> - ApplicationMessage: removed app field, new() takes only payload - New public type: MessageOrigin enum
2 parents 6aca62d + 82e6b23 commit 63dbf07

File tree

8 files changed

+1975
-2088
lines changed

8 files changed

+1975
-2088
lines changed

rust-macros/src/delegate_impl.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl ImplStruct {
2828
quote! {
2929
#[no_mangle]
3030
#[cfg(feature = "freenet-main-delegate")]
31-
pub extern "C" fn process(parameters: i64, attested: i64, inbound: i64) -> #ret {
31+
pub extern "C" fn process(parameters: i64, origin: i64, inbound: i64) -> #ret {
3232
#set_logger
3333
let parameters = unsafe {
3434
let param_buf = &*(parameters as *const ::freenet_stdlib::memory::buf::BufferBuilder);
@@ -38,16 +38,19 @@ impl ImplStruct {
3838
);
3939
Parameters::from(bytes)
4040
};
41-
let attested = unsafe {
42-
let attested_buf = &*(attested as *const ::freenet_stdlib::memory::buf::BufferBuilder);
41+
let origin: Option<::freenet_stdlib::prelude::MessageOrigin> = unsafe {
42+
let origin_buf = &*(origin as *const ::freenet_stdlib::memory::buf::BufferBuilder);
4343
let bytes = &*std::ptr::slice_from_raw_parts(
44-
attested_buf.start(),
45-
attested_buf.bytes_written(),
44+
origin_buf.start(),
45+
origin_buf.bytes_written(),
4646
);
4747
if bytes.is_empty() {
4848
None
4949
} else {
50-
Some(bytes)
50+
match ::freenet_stdlib::prelude::bincode::deserialize(bytes) {
51+
Ok(v) => Some(v),
52+
Err(_) => None,
53+
}
5154
}
5255
};
5356
let inbound = unsafe {
@@ -70,7 +73,7 @@ impl ImplStruct {
7073
let result = <#type_name as ::freenet_stdlib::prelude::DelegateInterface>::process(
7174
&mut ctx,
7275
parameters,
73-
attested,
76+
origin,
7477
inbound
7578
);
7679
::freenet_stdlib::prelude::DelegateInterfaceResult::from(result).into_raw()

rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "freenet-stdlib"
3-
version = "0.2.2"
3+
version = "0.3.0"
44
edition = "2021"
55
rust-version = "1.80"
66
publish = true

rust/src/client_api/client_events.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,19 +1443,11 @@ impl HostResponse {
14431443
let mut messages: Vec<WIPOffset<FbsOutboundDelegateMsg>> = Vec::new();
14441444
values.iter().for_each(|msg| match msg {
14451445
OutboundDelegateMsg::ApplicationMessage(app) => {
1446-
let instance_data = builder.create_vector(key.bytes());
1447-
let instance_offset = FbsContractInstanceId::create(
1448-
&mut builder,
1449-
&ContractInstanceIdArgs {
1450-
data: Some(instance_data),
1451-
},
1452-
);
14531446
let payload_data = builder.create_vector(&app.payload);
14541447
let delegate_context_data = builder.create_vector(app.context.as_ref());
14551448
let app_offset = FbsApplicationMessage::create(
14561449
&mut builder,
14571450
&ApplicationMessageArgs {
1458-
app: Some(instance_offset),
14591451
payload: Some(payload_data),
14601452
context: Some(delegate_context_data),
14611453
processed: app.processed,

rust/src/delegate_interface.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::common_generated::common::SecretsId as FbsSecretsId;
2020

2121
use crate::client_api::{TryFromFbs, WsApiError};
2222
use crate::contract_interface::{RelatedContracts, UpdateData};
23-
use crate::prelude::{ContractInstanceId, WrappedState, CONTRACT_KEY_SIZE};
23+
use crate::prelude::{ContractInstanceId, WrappedState};
2424
use crate::versioning::ContractContainer;
2525
use crate::{code_hash::CodeHash, prelude::Parameters};
2626

@@ -363,6 +363,18 @@ impl<'a> TryFromFbs<&FbsSecretsId<'a>> for SecretsId {
363363
}
364364
}
365365

366+
/// Identifies where an inbound application message originated from.
367+
///
368+
/// When a web app sends a message to a delegate through the WebSocket API with
369+
/// an authentication token, the runtime resolves the token to the originating
370+
/// contract and wraps it in `MessageOrigin::WebApp`. Delegates receive this as
371+
/// the `origin` parameter of [`DelegateInterface::process`].
372+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
373+
pub enum MessageOrigin {
374+
/// The message was sent by a web application backed by the given contract.
375+
WebApp(ContractInstanceId),
376+
}
377+
366378
/// A Delegate is a webassembly code designed to act as an agent for the user on
367379
/// Freenet. Delegates can:
368380
///
@@ -391,7 +403,7 @@ impl<'a> TryFromFbs<&FbsSecretsId<'a>> for SecretsId {
391403
/// fn process(
392404
/// ctx: &mut DelegateCtx,
393405
/// _params: Parameters<'static>,
394-
/// _attested: Option<&'static [u8]>,
406+
/// _origin: Option<MessageOrigin>,
395407
/// message: InboundDelegateMsg,
396408
/// ) -> Result<Vec<OutboundDelegateMsg>, DelegateError> {
397409
/// // Access secrets synchronously - no round-trip needed!
@@ -415,13 +427,13 @@ pub trait DelegateInterface {
415427
/// - **Context** (temporary): `read()`, `write()`, `len()`, `clear()` - state within a batch
416428
/// - **Secrets** (persistent): `get_secret()`, `set_secret()`, `has_secret()`, `remove_secret()`
417429
/// - `parameters`: The delegate's initialization parameters.
418-
/// - `attested`: An optional identifier for the client of this function. Usually
419-
/// will be a [`ContractInstanceId`].
430+
/// - `origin`: An optional [`MessageOrigin`] identifying where the message came from.
431+
/// For messages sent by web applications, this is `MessageOrigin::WebApp(contract_id)`.
420432
/// - `message`: The inbound message to process.
421433
fn process(
422434
ctx: &mut crate::delegate_host::DelegateCtx,
423435
parameters: Parameters<'static>,
424-
attested: Option<&'static [u8]>,
436+
origin: Option<MessageOrigin>,
425437
message: InboundDelegateMsg,
426438
) -> Result<Vec<OutboundDelegateMsg>, DelegateError>;
427439
}
@@ -555,11 +567,7 @@ impl<'a> TryFromFbs<&FbsInboundDelegateMsg<'a>> for InboundDelegateMsg<'a> {
555567
match msg.inbound_type() {
556568
InboundDelegateMsgType::common_ApplicationMessage => {
557569
let app_msg = msg.inbound_as_common_application_message().unwrap();
558-
let mut instance_key_bytes = [0; CONTRACT_KEY_SIZE];
559-
instance_key_bytes
560-
.copy_from_slice(app_msg.app().data().bytes().to_vec().as_slice());
561570
let app_msg = ApplicationMessage {
562-
app: ContractInstanceId::new(instance_key_bytes),
563571
payload: app_msg.payload().bytes().to_vec(),
564572
context: DelegateContext::new(app_msg.context().bytes().to_vec()),
565573
processed: app_msg.processed(),
@@ -585,16 +593,14 @@ impl<'a> TryFromFbs<&FbsInboundDelegateMsg<'a>> for InboundDelegateMsg<'a> {
585593
#[non_exhaustive]
586594
#[derive(Serialize, Deserialize, Debug, Clone)]
587595
pub struct ApplicationMessage {
588-
pub app: ContractInstanceId,
589596
pub payload: Vec<u8>,
590597
pub context: DelegateContext,
591598
pub processed: bool,
592599
}
593600

594601
impl ApplicationMessage {
595-
pub fn new(app: ContractInstanceId, payload: Vec<u8>) -> Self {
602+
pub fn new(payload: Vec<u8>) -> Self {
596603
Self {
597-
app,
598604
payload,
599605
context: DelegateContext::default(),
600606
processed: false,

0 commit comments

Comments
 (0)