-
Notifications
You must be signed in to change notification settings - Fork 4
Blockchain tracking
The architecture of wallet tracking in OPEN State is implemented in such a way that it is easier to add new integrations with blockchains. To do this, you just need to create your own class, inherit from a blockchain and implement its methods. After that, it is imperative to mark it as a bean, so that later your implementation will be noticed by the Spring context.
There are two jobs involved in wallet tracking:
- Blockchain processor
- Blockchain checker
This processor wakes up at certain time with fixed delay after each execution. Utilizing a coroutine scope, it receives one random blockchain from the Redis queue, which needs to be processed. After, it will immediately try to lock this blockchain for processing by adding a value in Redis. The idea behind this solution is that more than one OPEN State instance will be launched on the servers, and to not allow several jobs to do the processing at the same time. This solution allows you to not load servers and guarantees the correct processing of blocks. If the processor fails to take over(lock) for processing, then we would consider that this blockchain is already being processed by another job. Otherwise, we get the number of the last processed block for the current blockchain from Redis. After, through this block number, we get all transactions and find wallets that need to be tracked, saving them in MongoDB. Furthermore, after processing, we increase the number of the currently processed block in Redis. At this point, it is worth emphasizing that after each block is processed, we update the lock that we mentioned earlier, since on Redis this is implemented through a timeout. That is, if the processor does not complete the work at the specified time, then the blockchain will be automatically removed from the locks in Redis. Accordingly, another processor will take over. This whole process is performed in a loop until this job processes til the last block(last> current). After iterating these operations, it is logical to release the lock for the current blockchain by deleting the value in Redis.
The structure of storage in Redis is as follows:
It is worth noting that the blockchain used below is the name of the class that is inherited from the parent blockchain class. For example, the already integrated Ethereum - in this case, it will be EthereumBlockchain.
- [queue]: blockchain. Used to store blockchain queues. Blockchain checker adds when a new block appears, and the Blockchain processor reads
- [lock: blockchain]: timestamp. Stored for locking blockchain described in Blockchain processor
- [blockchain: current]: value. Current processed block number stored
- [blockchain: last]: value. Last known block number stored
This job wakes up at certain time with fixed delay after each execution. This process is needed to periodically check for new unprocessed blocks. Firstly, when launching the kotlin coroutine, it will go through each blockchain with which OPEN State was integrated. Also, for each blockchain it will request from the implementation (by calling the getLastBlockNumber method which obliges to implement this method) the last block number in the system. In addition, when receiving information about the last known block from Redis, it compares these block numbers. If these values are not equal, then we update the value of the last block in Redis for a blockchain. Additionally, we add the current blockchain in the queue in Redis, so that the Blockchain processor will be processed later. Otherwise, if these values are equal, we simply end the processing of the current blockchain, since we already know the current block number and there is no need to trigger Redis.