## 5 The Proposed Approach
### Verification Phase  
Once the communication phase is completed, the verification of message integrity for the current temporal round \(R_{i}\) begins. This phase involves several steps performed by the broker \(B\) and the clients (the publisher \(P\) and all the subscribers \(S\)).  
\(B\) proceeds as follows. At the end of the round \(R_{i}\), it first publishes the Merkle hash tree \(M_{i}\) on IPFS. As described in Section 2, in IPFS, each stored object is identified by a unique hash. We call this address IPFS_Addr\({}_{M_{i}}\). Then, \(B\) invokes the addRootIPFSAddress function on the smart contract with the following inputs: \(\text{Root}_{M_{i}}\) and IPFS_Addr\({}_{M_{i}}\). The smart contract stores this pair, thus creating a permanent link between the MHT root and its storage location on IPFS.  
\(P\) proceeds as follows. At the end of the round \(R_{i}\), \(P\) independently constructs a Merkle hash tree \(M_{i}^{*}\) of the messages exchanged during \(R_{i}\) with \(B\). Thus, \(P\) locally computes its root hash \(\text{Root}_{M_{i}}^{*}\) and verifies it against the roots recorded in the smart contract. Specifically, \(P\) invokes the getIPFSAddress function on the smart contract with the locally computed root Root\({}_{M_{i}}^{*}\). The function returns the related IPFS address if a matching root is found. If the returned IPFS address is 0, it indicates that the root Root\({}_{M_{i}}^{*}\) computed by \(P\) does not match any root stored by the broker. In this case, the smart contract emits a PublisherAlert event to signal there is an integrity violation, i.e., the messages published by the broker are different from those received by the subscribers. This way, all the subscribers who monitor these events in real-time are immediately notified of the integrity violation in the message stream for the round \(R_{i}\).  
Then, also, each subscriber \(S\) proceeds with the verification phase. \(S\) verifies that the root hash \(\text{Root}_{M_{i}}^{**}\) received from \(B\) is stored in the blockchain by invoking the getIPFSAddress function on the smart contract. If no match is found on the blockchain, the smart contract emits the \(\text{SubscriberAlert}\) event notifying all participants of this. If the root hash matches (i.e., \(\text{Root}_{M_{i}}^{*}=\text{Root}_{M_{i}}\)), \(S\) proceeds to verify the integrity of the computed hashchains. \(S\) requests from \(B\) the missing hash values necessary to construct the path from the final hash value of the local hashchain to the root \(\text{Root}_{M_{i}}\). In the case that \(S\) cannot reconstruct at least one of these paths, it invokes the getIPFSAddress function with a deliberately incorrect root hash (e.g., 0) to trigger an alert for all participants, ensuring they are aware of the issue. Thisway, all monitoring participants (publishers and subscribers) are immediately notified of the integrity violation.  
This verification phase ensures robust end-to-end integrity guarantees within the MQTT framework. Indeed, during each round time, both publishers and subscribers can check whether the messages sent by the publisher have not been tampered with while in transit.