Hi devs!
Recently our team discover that our system is not implement correct due to prevent reentrancy issue.
We have one backend method update_action
sequentially does:
-
loop all the transaction of action, check it is valid to execute
-
for each executable transaction
2.1 update transaction to processing
2.2 spawn timeout task -
If transaction have to execute by current canister
3.1 call ledger canister to transfer fund (Async) -
If transaction is user’s transaction, prepare list of transaction (List A) wallet have to execute
-
Return current action and List A for client to execute
The method update_action
designed to be triggered multiple times for one action. But it can be compromise by bad actor to make reentrancy issue
So we are thinking adding a new lock mechanism
-
Create a lock for action id, store it in stable memory
-
loop all the transaction of action, check it is valid to execute
-
for each executable transaction
2.1 update transaction to processing
2.2 spawn timeout task -
If transaction have to execute by current canister
3.1 call ledger canister to transfer fund (Async) -
If transaction is user’s transaction, prepare list of transaction (List A) wallet have to execute
-
Delete the lock record
-
Return current action and List A for client to execute
From what I know, if there is one transaction
from 1 → before 3 is one message execution
and from 3 → 7 is another message execution
Question
Is that any guarantee that 3 → 7 always executed after subnet is downed?