-
Notifications
You must be signed in to change notification settings - Fork 60
RUES (Rusk Universal Event System)
The Rusk Universal Event System (RUES) is a key component of the Dusk blockchain network, facilitating real-time communication and interactions across the ecosystem. This document delineates the specifications for event dispatch, subscription, and unsubscription within the RUES framework for external clients.
Clients may engage with a Rusk node through the operations: dispatch, subscribe, and unsubscribe. These interactions employ the HTTP protocol. An active session between the client and the node is a prerequisite for receiving events.
A session is established through an initial handshake, which involves requesting a WebSocket connection from a Rusk node. A successful handshake results in the client receiving a Rusk-Session-Id
as the initial message, which is essential for subsequent event subscription and unsubscription actions. This session identifier is a nonce consisting of a randomly selected 16-byte value that has been base16-encoded.
Future implementations may consider using HTTP Origin-Bound Authentication (HOBA).
Note
A node may refuse the connection at its discretion. Reasons for refusal can include, among others, an excessive number of current connections or the node's configurations restricting the availability of event interactions to external clients.
The WebSocket connection serves as the conduit for transmitting subscribed events to the client. In load-balanced environments, it is crucial to ensure consistent routing of requests to the same server instance.
Either party — client or Rusk node — may terminate a session by closing the WebSocket connection, which automatically unsubscribes all associated events.
Events within the system, whether they are dispatched, subscribed to, or unsubscribed from, are uniformly identified by a unique relative URL. This URL is structured as follows:
/on/[target]/[topic]
The components of this URL are detailed in the table below:
URL | Value | Description |
---|---|---|
pathname | on |
A fixed value that designates the events service. |
pathname | [target] |
The event target. |
pathname | [topic] |
The specific topic of the event. |
In the RUES system, the [target]
portion of the URL uniquely identifies the target of the event. This segment can represent a general component
or a specific element within that component. Examples of general component targets include:
/on/contracts/deploy
/on/transactions/accepted
For more specific targeting, the URL can specify an individual element within a component, utilizing the colon :
character to delineate the element. Here are some examples:
/on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/deploy
/on/transactions:fe2ffdcdd27be82fc850bc269ff87fb8e72cf0cd4368e49fe947afeb48167f08/accepted
Important
In these URLs, the colon :
serves as a delimiter that differentiates between the component and its specific element. It is important to note that when the colon appears as part of a component or element name, it must be URL-encoded as %3A
. However, when used as a delimiter as shown above, it must not be encoded.
Clients subscribe to events by issuing a GET HTTP request to the node, structured as follows:
GET https://[node address][event identification]
A hypothetical events subscription for a contract could be:
GET https://nodes.dusk.network/on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/item-added
GET https://nodes.dusk.network/on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/item-removed
GET https://nodes.dusk.network/on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/item-changed
Name | Description |
---|---|
Rusk-Version |
Specifies the compatible Rusk version |
Rusk-Session-Id |
Identifies the current session |
Status code | When |
---|---|
200 OK |
Successful subscription |
400 Bad Request |
Rusk-Version incompatibility |
424 Failed Dependency |
Rusk-Session-Id issues |
404 Not Found |
[component] or [target] not found |
Note
- Clients may subscribe to events that the contract may never actually emit.
- The contract's address is base16-encoded.
Unsubscription mimics the subscription process but employs the DELETE
method:
DELETE https://[node address][event identification]
DELETE https://nodes.dusk.network/on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/item-changed
DELETE https://nodes.dusk.network/on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/item-removed
DELETE https://nodes.dusk.network/on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/item-changed
Name | Description |
---|---|
Rusk-Version |
Specifies the compatible Rusk version |
Rusk-Session-Id |
Identifies the current session |
Status code | When |
---|---|
200 OK |
Successful unsubscription |
400 Bad Request |
Rusk-Version incompatibility |
424 Failed Dependency |
Rusk-Session-Id issues |
404 Not Found |
[component] , [target] or [topic] not found |
Note
A prerequisite for unsubscribing from a topic
is that it must have been previously subscribed to; failure to meet this condition will result in a 404 Not Found
error. This represents a notable distinction from the subscription process.
To dispatch events, clients use a POST request, potentially including a payload in the request body:
POST https://[node address][event identification]
Dispatching an event is very different from the other two method, since it will most likely have a body
, that is the payload
of the event.
POST https://nodes.dusk.network/on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/sync
[content]
Name | Description |
---|---|
Rusk-Version |
Specifies the compatible Rusk version |
Rusk-Session-Id |
Identifies the current session |
Content-Type |
Usually application/json or application/octet-stream
|
Content-Length |
The length of the message body in octets (8-bit bytes). |
Accept |
Media type(s) that is/are acceptable for a response message |
In this context, the Rusk-Session-Id
is optional, accommodating scenarios where a client dispatches an event for an immediate response or for a transaction that does not require subsequent interaction, effectively a "fire-and-forget" operation.
Status code | When |
---|---|
200 OK |
The event was received successfully and a response is generated in return |
202 Accepted |
The event was received successfully. |
400 Bad Request |
Rusk-Version mismatch |
424 Failed Dependency |
Rusk-Session-Id does not match |
404 Not Found |
[component] and/or [target] and/or [topic] cannot be found |
422 Unprocessable Content |
The event's payload cannot processed with the Content-Type given |
Subscribed events are delivered via the WebSocket connection in binary format, structured to include header information followed by the event payload.
Type | Description |
---|---|
u32 |
The length of the headers in LE |
[u8] |
JSON-formatted request headers |
[u8] |
Event data |
The message's header mimic the HTTP header, and are stored in a JSON key / value dictonary of type { String : String }
Name | Description |
---|---|
Content-Location |
Event dispatch URL's pathname (e.g. /on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/item-added
|
Content-Type |
Usually application/json or application/octet-stream
|
Content-Length |
The length of the message body in octets (8-bit bytes). |
Important
The Content-Location
header consistently includes the complete identifier for the target of the event. For instance, if the operation is GET /on/deploy/contracts
, the Content-Location
will specify the exact contract affected by the event, such as /on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/item-added
.
Note
The streaming of messages at the moment is not supported, since we're not expecting a single event to deliver more than 2^63 bytes.
Event interactions with a node, including dispatching, subscribing, and unsubscribing, are facilitated through HTTP methods and share a common URL structure tailored to each event. This setup allows for granular access control at the proxy level, enabling precise restriction of event operations even when the node permits external client interactions.
The following table illustrates various access restrictions that can be applied to event operations based on HTTP methods and URL patterns:
Restriction | Description |
---|---|
DENY GET /on/ |
Blocks subscription and unsubscription operations (unsubscription requires a pre-existing subscription); however, dispatching events remains permitted. |
DENY GET, POST /on/ |
Prevents subscription, unsubscription, and dispatching operations across all events. |
DENY GET, POST /on/contracts/ |
Disallows subscription, unsubscription, and dispatching for events related to the contracts component, while permitting these operations for contracts' entities and other components (e.g., chain ). |
DENY GET, POST /on/contracts:*/ |
Disallows subscription, unsubscription, and dispatching for events related to the contracts' elements, while permitting these operations for contracts and other components (e.g., chain ). |
DENY GET, POST /on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/* |
Restricts subscription, unsubscription, and dispatching for events associated with the specific contract efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da , but allows for other contracts and components. |
DENY GET /on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/item-changed |
Blocks subscription to the specific event item-changed for the target contract. |
DENY POST /on/contracts:efda355bc94a3be09006dc90f3714a0ee22c586c5e577e429ef3b5e3e464a8da/sync/ |
Prohibits dispatching the specific event sync for the targeted contract. |
DENY POST /on/contracts/sync |
Forbids dispatching the sync event for any contract within the contracts component. |
This structured approach ensures that nodes can maintain a high degree of security and operational integrity by precisely controlling how and by whom event operations are conducted.