Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
f7452d8
add root hash for state accesses event
ssd04 Sep 30, 2025
d182636
fix scheduled root hash
BeniaminDrasovean Sep 30, 2025
625139a
update logging
BeniaminDrasovean Oct 7, 2025
456819d
update logging
BeniaminDrasovean Oct 7, 2025
885db03
remove duplicates from txsWithOrder
BeniaminDrasovean Oct 7, 2025
23fb34f
Merge branch 'rc/supernova' into state-accesses-roothash
ssd04 Oct 10, 2025
d2d0ae1
fixes after merge
ssd04 Oct 10, 2025
e269c11
cleanup logs
ssd04 Oct 30, 2025
f3b5eab
add state accesses in unit tests
ssd04 Oct 30, 2025
e282c87
adapt to use header and metablock v3
ssd04 Nov 11, 2025
c0f9f20
handle logs events from execution results
ssd04 Nov 11, 2025
e1c209c
refactor to handle block data for v3
ssd04 Nov 12, 2025
640c394
add unit tests
ssd04 Nov 12, 2025
5a79367
small renamings
ssd04 Nov 12, 2025
1f62faf
fixes after review
ssd04 Nov 17, 2025
6adae9a
Merge pull request #127 from multiversx/integrate-header-v3-execution…
ssd04 Nov 17, 2025
7471e4a
fix tx pool nil checks
ssd04 Nov 17, 2025
c0f5d4f
add test data for v3
ssd04 Nov 17, 2025
9784855
add TODO for integration tests updates for v3
ssd04 Nov 17, 2025
a2baa42
add error logging
ssd04 Nov 18, 2025
b98eddf
adapt integrationt test for v3
ssd04 Nov 18, 2025
ce9be57
added more integration tests for v3
ssd04 Nov 19, 2025
76638e2
Merge pull request #128 from multiversx/fix-tx-pool-check
ssd04 Nov 19, 2025
c5cb0c7
Merge pull request #130 from multiversx/adapt-integration-tests-v3
ssd04 Nov 27, 2025
c3b7e1c
adapt stateAccesses for supernova
BeniaminDrasovean Nov 27, 2025
c54dcea
Merge remote-tracking branch 'origin/rc/supernova' into stateAccesses…
BeniaminDrasovean Nov 27, 2025
7df9814
fix after merge
BeniaminDrasovean Nov 27, 2025
3903d68
Merge remote-tracking branch 'origin/stateAccesses-for-supernova' int…
BeniaminDrasovean Dec 4, 2025
fb6626a
fix after merge
BeniaminDrasovean Dec 4, 2025
fca6452
update for headerV3
BeniaminDrasovean Dec 4, 2025
dff0aca
add nonce from execResult
BeniaminDrasovean Dec 11, 2025
22c363d
fix nonce for stateAccesses
BeniaminDrasovean Dec 11, 2025
f4919cd
update go mod
BeniaminDrasovean Dec 16, 2025
87ee016
Merge pull request #131 from multiversx/stateAccesses-for-supernova
ssd04 Jan 5, 2026
e7a11ba
bump core-go
ssd04 Jan 23, 2026
28e4b02
fix execution result timestamp
ssd04 Jan 23, 2026
a03c8cf
update test data
ssd04 Jan 23, 2026
a790a68
add common func
ssd04 Jan 23, 2026
bcb59a6
Revert "update test data"
ssd04 Jan 23, 2026
27472c0
Reapply "update test data"
ssd04 Jan 23, 2026
08337d3
revert test data addr
ssd04 Jan 23, 2026
22fe7ba
Merge pull request #132 from multiversx/fix-exec-result-timestamp
ssd04 Jan 28, 2026
9de8c98
update unnecessary warn logs
ssd04 Jan 30, 2026
41402d9
add duration logs for entire flow
ssd04 Jan 30, 2026
e311ca3
update communication-go
ssd04 Feb 5, 2026
d132de5
Merge pull request #134 from multiversx/update-comm-go
ssd04 Feb 5, 2026
70ab334
Merge pull request #133 from multiversx/add-more-logging
ssd04 Feb 6, 2026
587a7ee
use latest core-go tag reference
ssd04 Feb 11, 2026
834d210
Merge branch 'main' into merge-main-into-rc-supernova
ssd04 Feb 11, 2026
03e2acb
fix merge conflicts
ssd04 Feb 11, 2026
5bc84e0
Merge pull request #136 from multiversx/merge-main-into-rc-supernova
ssd04 Feb 11, 2026
d91ca59
Merge pull request #135 from multiversx/update-core-go
ssd04 Feb 11, 2026
b5d5b63
Merge remote-tracking branch 'origin/rc/supernova' into state-accesse…
BeniaminDrasovean Feb 11, 2026
63e85b9
update go mod
BeniaminDrasovean Feb 11, 2026
98d6dbb
use backwards compatible state accesses per txs
ssd04 Mar 4, 2026
57b40dd
add state accesses also for outport integration v0
ssd04 Mar 4, 2026
05f3db4
small fixes
ssd04 Mar 4, 2026
e9abe38
Merge remote-tracking branch 'origin/state-accesses-backwards-compati…
BeniaminDrasovean Mar 4, 2026
ab0dac9
change config
BeniaminDrasovean Mar 4, 2026
17e1fc0
remove scheduled root hash field
ssd04 Mar 5, 2026
6a10d12
revert config changes
ssd04 Mar 5, 2026
119ce1a
update core-go version
ssd04 Mar 5, 2026
5caefd1
Merge pull request #137 from multiversx/state-accesses-backwards-comp…
ssd04 Mar 5, 2026
fa93417
Merge pull request #120 from multiversx/state-accesses-roothash
ssd04 Mar 5, 2026
6bae7ca
Revert "add root hash for state accesses event"
ssd04 Mar 5, 2026
4c619f1
update core-go version
ssd04 Mar 5, 2026
c66cedb
Merge pull request #138 from multiversx/revert-120-state-accesses-roo…
ssd04 Mar 5, 2026
3cbc034
ws vs http integration distinction
ssd04 Mar 6, 2026
3477a5e
update event types section
ssd04 Mar 6, 2026
ba48f43
fixes after review
ssd04 Mar 6, 2026
10089b8
Merge pull request #139 from multiversx/update-readme
ssd04 Mar 9, 2026
f9c2dfb
fix header gas consumption check
BeniaminDrasovean Mar 16, 2026
e17536d
fix test
BeniaminDrasovean Mar 16, 2026
804b69b
add nil check for execRes
BeniaminDrasovean Mar 16, 2026
cdfc335
Merge pull request #140 from multiversx/header-gas-consumption-check-fix
ssd04 Mar 16, 2026
bdc53da
do not WARN if no state change found for SCR tx
BeniaminDrasovean Mar 17, 2026
fa4a916
add missing comment
BeniaminDrasovean Mar 17, 2026
2665bb7
unexport constants
BeniaminDrasovean Mar 17, 2026
126b339
Merge pull request #141 from multiversx/state-changes-WARN-pollution-fix
BeniaminDrasovean Mar 17, 2026
aee1394
remove duplicated txs
BeniaminDrasovean Mar 19, 2026
bd16a9f
add unit test
BeniaminDrasovean Mar 19, 2026
1eff8a1
fixes after review
BeniaminDrasovean Mar 23, 2026
b5a6e3b
small refactor
BeniaminDrasovean Mar 23, 2026
2ea594e
Merge pull request #142 from multiversx/remove-duplicated-txs
BeniaminDrasovean Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 118 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The notifier service is a component that receives block events synchronously
from multiversx observer nodes, and it forwards them to a subscribing component
(via message queuing service or websockets)
(via message queuing service or websockets).

## Prerequisites

Expand All @@ -11,15 +11,12 @@ has to setup one or multiple observers. For running an observing squad,
these [docs](https://docs.multiversx.com/integrators/observing-squad/)
cover the whole process.

The observer node can be connected using WebSocket integration. Please check observer
node config for setting up the connector. Enable `HostDriversConfig` in order to use
WebSocket integration.
There are two ways the observer nodes can push data to the notifier service:

The required configs for launching an observer/s with a driver attached,
can be found [here](https://github.com/multiversx/mx-chain-go/blob/master/cmd/node/config/external.toml).
1. **WebSocket Integration (Recommended)**: The observer node pushes events to the notifier over a persistent WebSocket connection. This is the newer, more efficient method. To use this, check the observer node config and enable `HostDriversConfig`.
The required configs for launching an observer/s with a WS driver attached can be found [here](https://github.com/multiversx/mx-chain-go/blob/master/cmd/node/config/external.toml).

The HTTP integration is still available for backwards compatibility, but it will be
deprecated in the future.
2. **HTTP POST Integration (Deprecated)**: The observer node makes separate HTTP POST requests to the notifier's API endpoints (`/events/push`, etc.) for every event. This integration is still available for backwards compatibility, but it will be deprecated in the future.

## How to run

Expand Down Expand Up @@ -64,6 +61,8 @@ The supported config variables are:
as the one specified in the `ProxyUrl` described above.
- `Username`: the username used to authorize an observer. Can be left empty for `UseAuthorization = false` on observer connector.
- `Password`: the password used to authorize an observer. Can be left empty for `UseAuthorization = false` on observer connector.
- `CheckDuplicates`: signals if the events received from observers have already been pushed to clients. Requires a Redis instance/cluster.
- `WithReadStateChanges`: signals if read state changes operations will be handled by the notifier. Note: this requires read state changes to also be enabled on the observer nodes.

If observer connector is set to use BasicAuth with `UseAuthorization = true`, `Username` and `Password` has to be
set here on events notifier, and `Auth` flag has to be enabled in
Expand Down Expand Up @@ -131,16 +130,22 @@ make docker-new publisher_type=rabbitmq

### API Endpoints

Notifier service will expose several events routes, the observer nodes will
push events to these routes:
Depending on the observer integration method chosen, the notifier service will expose the following routes.

**For WebSocket Integration (Observer -> Notifier):**
When using the WebSocket integration, the observer pushes all events through a single persistent WebSocket connection rather than relying on the HTTP routes below.

**For HTTP POST Integration (Observer -> Notifier):**
The observer nodes will push events to these routes via consecutive HTTP requests:
- `/events/push` (POST) -> it will handle all events for each round
- `/events/revert` (POST) -> if there is a reverted block, the event will be
pushed on this route
- `/events/finalized` (POST) -> when the block has been finalized, the events
will be pushed on this route

If the service will be in "notifier" mode, it will expose a additional route:
- `/hub/ws` (GET) - this route can be used to manage the websocket connection (check [websocket subscribing](#websockets) section for more details on this)
**For Client Subscriptions (Notifier -> Consumer):**
If the service will be in "notifier" mode (using the `ws` publisher), it will expose an additional route for end consumers to receive data:
- `/hub/ws` (GET) - this route can be used to manage the WebSocket connection (check [websocket subscribing](#websockets) section for more details on this)

## Redis

Expand All @@ -166,10 +171,110 @@ in code in `data/outport.go` file.
Once the proxy is launched together with the observer/s, the driver's methods
will be called.

### Event types

There are multiple event types available, they can be found as constants in common package,
[constants](https://github.com/multiversx/mx-chain-notifier-go/blob/main/common/constants.go).
Below is the list of available event types together with their associated JSON payload structures.

- `all_events`: Pushes all logs and events for a block.
```json
{
"hash": "blockHash1",
"events": [
{
"address": "addr1",
"identifier": "identifier",
"topics": ["<< base64 encoded topic1 >>", "<< base64 encoded topic2 >>"],
"data": "<< base64 encoded data >> ",
...
}
]
}
```

- `block_events`: Pushes block info alongside its logs and events.
```json
{
"hash": "blockHash1",
"shardId": 1,
"timestamp": 12345678,
"timestampMs": 12345678000,
"events": [
{
"address": "addr1",
"identifier": "identifier",
...
}
]
}
```

- `revert_events`: Pushes information relating to a reverted block.
```json
{
"hash": "blockHash1",
"nonce": 11,
"round": 2,
"epoch": 1,
"shardId": 1,
"timestamp": 12345678,
"timestampMs": 12345678000
}
```

- `finalized_events`: Pushes the hash of a finalized block.
```json
{
"hash": "blockHash"
}
```

- `block_txs`: Pushes all transactions contained within a block.
```json
{
"hash": "blockHash1",
"txs": {
"txHash1": {
"Nonce": 123,
"Round": 1,
"Epoch": 1,
...
}
}
}
```

- `block_scrs`: Pushes all smart contract results contained within a block.
```json
{
"hash": "blockHash1",
"scrs": {
"scrHash1": {
"Nonce": 123,
...
}
}
}
```

- `block_state_accesses`: Pushes information regarding the state accesses (reads/writes) occurring within a block. *(Requires `WithReadStateChanges` config enabled)*
```json
{
"hash": "blockHash1",
"shardID": 1,
"timestampMs": 12345678000,
"nonce": 123,
"stateAccessesPerAccounts": {
...
}
}
```

### RabbitMQ

When using a setup with `RabbitMQ` you have to subscribe to each exchange
separately.
separately. This can be handled via RabbitMQ Management UI platform.

### WebSockets

Expand Down Expand Up @@ -295,63 +400,3 @@ inner marshalled data like:
}
```

There are multiple event types available, they can be found as constants in common package,
[constants](https://github.com/multiversx/mx-chain-notifier-go/blob/main/common/constants.go). Below there is the event type together with the associated marshalled data type.
- `all_events`
```json
{
"hash": "blockHash1",
"events": [
{
"address": "addr1",
"identifier": "identifier",
...
}
]
}
```

- `revert_events`
```json
{
"hash": "blockHash1",
"nonce": 11,
"round": 2,
"epoch": 1,
}
```

- `finalized_events`
```json
{
"hash": "blockHash"
}
```

- `block_txs`:
```json
{
"hash": "blockHash1",
"txs": {
"txHash1": {
"Nonce": 123,
"Round": 1,
"Epoch": 1,
...
}
}
}
```

- `block_scrs`
```json
{
"hash": "blockHash1",
"scrs": {
"scrHash1": {
"Nonce": 123,
...
}
}
}
```
6 changes: 6 additions & 0 deletions api/groups/eventsGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func getPayloadVersion(c *gin.Context) uint32 {
func (h *eventsGroup) pushEvents(c *gin.Context) {
pushEventsRawData, err := c.GetRawData()
if err != nil {
log.Error("pushEvents: failed to get raw data", "error", err)
shared.JSONResponse(c, http.StatusBadRequest, nil, err.Error())
return
}
Expand All @@ -106,6 +107,7 @@ func (h *eventsGroup) pushEvents(c *gin.Context) {

err = h.payloadHandler.ProcessPayload(pushEventsRawData, outport.TopicSaveBlock, payloadVersion)
if err != nil {
log.Error("pushEvents: failed to process payload", "error", err)
shared.JSONResponse(c, http.StatusBadRequest, nil, err.Error())
return
}
Expand All @@ -116,6 +118,7 @@ func (h *eventsGroup) pushEvents(c *gin.Context) {
func (h *eventsGroup) revertEvents(c *gin.Context) {
revertEventsRawData, err := c.GetRawData()
if err != nil {
log.Error("revertEvents: failed to get raw data", "error", err)
shared.JSONResponse(c, http.StatusBadRequest, nil, err.Error())
return
}
Expand All @@ -124,6 +127,7 @@ func (h *eventsGroup) revertEvents(c *gin.Context) {

err = h.payloadHandler.ProcessPayload(revertEventsRawData, outport.TopicRevertIndexedBlock, payloadVersion)
if err != nil {
log.Error("revertEvents: failed to process payload", "error", err)
shared.JSONResponse(c, http.StatusBadRequest, nil, err.Error())
return
}
Expand All @@ -134,6 +138,7 @@ func (h *eventsGroup) revertEvents(c *gin.Context) {
func (h *eventsGroup) finalizedEvents(c *gin.Context) {
finalizedRawData, err := c.GetRawData()
if err != nil {
log.Error("finalizedEvents: failed to get raw data", "error", err)
shared.JSONResponse(c, http.StatusBadRequest, nil, err.Error())
return
}
Expand All @@ -142,6 +147,7 @@ func (h *eventsGroup) finalizedEvents(c *gin.Context) {

err = h.payloadHandler.ProcessPayload(finalizedRawData, outport.TopicFinalizedBlock, payloadVersion)
if err != nil {
log.Error("finalizedEvents: failed to process payload", "error", err)
shared.JSONResponse(c, http.StatusBadRequest, nil, err.Error())
return
}
Expand Down
2 changes: 1 addition & 1 deletion api/groups/eventsGroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func TestEventsGroup_PushEvents(t *testing.T) {
ExecutionOrder: 1,
},
},
Logs: []*outport.LogData{
Logs: []*transaction.LogData{
{
Log: &transaction.Log{
Address: []byte("logaddr1"),
Expand Down
6 changes: 6 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package common

// ConvertTimeStampMsToSec will convert unix timestamp from milliseconds to seconds
func ConvertTimeStampMsToSec(timeStamp uint64) uint64 {
return timeStamp / 1000
}
5 changes: 5 additions & 0 deletions data/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type InterceptorBlockData struct {
ScrsWithOrder map[string]*outport.SCRInfo
LogEvents []Event
StateAccessesPerAccounts map[string]*stateChange.StateAccesses
Nonce uint64
TimeStampMs uint64
}

// ArgsSaveBlockData holds the block data that will be received on push events
Expand All @@ -47,6 +49,8 @@ type ArgsSaveBlockData struct {
NumberOfShards uint32
HeaderTimeStampMs uint64
StateAccesses map[string]*stateChange.StateAccesses
StateAccessesForBlock map[string]*outport.StateAccessesForBlock
Results map[string]*outport.ExecutionResultData
}

// OutportBlockDataOld holds the block data that will be received on push events
Expand All @@ -62,6 +66,7 @@ type OutportBlockDataOld struct {
AlteredAccounts map[string]*alteredAccount.AlteredAccount
NumberOfShards uint32
IsImportDB bool
StateAccesses map[string]*stateChange.StateAccesses
}

// ArgsSaveBlock holds block data with header type
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ require (
github.com/go-redis/redis/v8 v8.11.3
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3
github.com/multiversx/mx-chain-communication-go v1.2.0
github.com/multiversx/mx-chain-core-go v1.4.1
github.com/multiversx/mx-chain-communication-go v1.3.0
github.com/multiversx/mx-chain-core-go v1.4.2-0.20260219122727-014ae9f9311f
github.com/multiversx/mx-chain-logger-go v1.1.0
github.com/pelletier/go-toml v1.9.3
github.com/prometheus/client_model v0.6.1
Expand Down Expand Up @@ -48,7 +48,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiversx/mx-chain-crypto-go v1.2.13-0.20250218161752-9482d9a22234 // indirect
github.com/multiversx/mx-chain-crypto-go v1.3.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiversx/mx-chain-communication-go v1.2.0 h1:0wOoLldiRbvaOPxwICbnRCqCpLqPewg8M/FMbC/0OXY=
github.com/multiversx/mx-chain-communication-go v1.2.0/go.mod h1:wS3aAwkmHbC9mlzQdvL6p7l8Rqw3vmzhj7WZW1dTveA=
github.com/multiversx/mx-chain-core-go v1.4.1 h1:ljs53jpdjtCohpaqm2n/dvTGrFlSgIpoZYH8RVt5cWo=
github.com/multiversx/mx-chain-core-go v1.4.1/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g=
github.com/multiversx/mx-chain-crypto-go v1.2.13-0.20250218161752-9482d9a22234 h1:NNI7kYxzsq+4mTPSUJo0cK1+iPxjUX+gRJDaBRwEQ7M=
github.com/multiversx/mx-chain-crypto-go v1.2.13-0.20250218161752-9482d9a22234/go.mod h1:QZAw2bZcOxGQRgYACTrmP8pfTa3NyxENIL+00G6nM5E=
github.com/multiversx/mx-chain-communication-go v1.3.0 h1:ziNM1dRuiR/7al2L/jGEA/a/hjurtJ/HEqgazHNt9P8=
github.com/multiversx/mx-chain-communication-go v1.3.0/go.mod h1:gDVWn6zUW6aCN1YOm/FbbT5MUmhgn/L1Rmpl8EoH3Yg=
github.com/multiversx/mx-chain-core-go v1.4.2-0.20260219122727-014ae9f9311f h1:kngckbX3TbZpU0LQpetUM8xNvUu/FtmZQtM66yoGcz0=
github.com/multiversx/mx-chain-core-go v1.4.2-0.20260219122727-014ae9f9311f/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g=
github.com/multiversx/mx-chain-crypto-go v1.3.0 h1:0eK2bkDOMi8VbSPrB1/vGJSYT81IBtfL4zw+C4sWe/k=
github.com/multiversx/mx-chain-crypto-go v1.3.0/go.mod h1:nPIkxxzyTP8IquWKds+22Q2OJ9W7LtusC7cAosz7ojM=
github.com/multiversx/mx-chain-logger-go v1.1.0 h1:97x84A6L4RfCa6YOx1HpAFxZp1cf/WI0Qh112whgZNM=
github.com/multiversx/mx-chain-logger-go v1.1.0/go.mod h1:K9XgiohLwOsNACETMNL0LItJMREuEvTH6NsoXWXWg7g=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
Expand Down
Loading
Loading