An account that confirms a transaction via AssetProxyOwner can indefinitely block that transaction
When a transaction reaches the required number of confirmations in `confirmTransaction()`, its confirmation time is recorded:\\n```\\n/// @dev Allows an owner to confirm a transaction.\\n/// @param transactionId Transaction ID.\\nfunction confirmTransaction(uint256 transactionId)\\n    public\\n    ownerExists(msg.sender)\\n    transactionExists(transactionId)\\n    notConfirmed(transactionId, msg.sender)\\n    notFullyConfirmed(transactionId)\\n{\\n    confirmations[transactionId][msg.sender] = true;\\n    emit Confirmation(msg.sender, transactionId);\\n    if (isConfirmed(transactionId)) {\\n        \\_setConfirmationTime(transactionId, block.timestamp);\\n    }\\n}\\n```\\n\\nBefore the time lock has elapsed and the transaction is executed, any of the owners that originally confirmed the transaction can revoke their confirmation via revokeConfirmation():\\n```\\n/// @dev Allows an owner to revoke a confirmation for a transaction.\\n/// @param transactionId Transaction ID.\\nfunction revokeConfirmation(uint256 transactionId)\\n    public\\n    ownerExists(msg.sender)\\n    confirmed(transactionId, msg.sender)\\n    notExecuted(transactionId)\\n{\\n    confirmations[transactionId][msg.sender] = false;\\n    emit Revocation(msg.sender, transactionId);\\n}\\n```\\n\\nImmediately after, that owner can call `confirmTransaction()` again, which will reset the confirmation time and thus the time lock.\\nThis is especially troubling in the case of a single compromised key, but it's also an issue for disagreement among owners, where any m of the n owners should be able to execute transactions but could be blocked.\\nMitigations\\nOnly an owner can do this, and that owner has to be part of the group that originally confirmed the transaction. This means the malicious owner may have to front run the others to make sure they're in that initial confirmation set.\\nEven once a malicious owner is in position to execute this perpetual delay, they need to call `revokeConfirmation()` and `confirmTransaction()` again each time. Another owner can attempt to front the attacker and execute their own `confirmTransaction()` immediately after the `revokeConfirmation()` to regain control.
There are several ways to address this, but to best preserve the original `MultiSigWallet` semantics, once a transaction has reached the required number of confirmations, it should be impossible to revoke confirmations. In the original implementation, this is enforced by immediately executing the transaction when the final confirmation is received.
```\\n/// @dev Allows an owner to confirm a transaction.\\n/// @param transactionId Transaction ID.\\nfunction confirmTransaction(uint256 transactionId)\\n    public\\n    ownerExists(msg.sender)\\n    transactionExists(transactionId)\\n    notConfirmed(transactionId, msg.sender)\\n    notFullyConfirmed(transactionId)\\n{\\n    confirmations[transactionId][msg.sender] = true;\\n    emit Confirmation(msg.sender, transactionId);\\n    if (isConfirmed(transactionId)) {\\n        \\_setConfirmationTime(transactionId, block.timestamp);\\n    }\\n}\\n```\\n