democratic-coin/dcoin-go

Loop after error on ChangePrimaryKey

Opened this issue · 1 comments

Проблема состоит в том, что ошибка при смене ключа может приводить к зацикливанию входа на страницу. Мне не удалось получить такую ситуацию в результате правильных действий, но в результате некоторых манипуляций зацикливание я получал. Не могу 100% утверждать, что описанное ниже истина, но по крайней мере очень похоже на правду.

Причина складывается из двух вещей.

  1. После ошибки при смене ключа у нас остается новый ключ в таблице my_keys со статусом my_pending. По хорошему, его наверно нужно удалять в Rollback функции. Но так как решение второго пункта обходит эту ситуацию, поэтому останавливаться на этом моменте не будем.
  2. Рассмотрим таблицу my_keys после ошибки. Самый первый ключ имеет block_id = 0 и статус approved. Новый ключ после ошибочной транзакции имеет тоже block_id = 0 и статус my_pending. Теперь рассмотрим функции GetMyPublicKey и GetMyPrivateKey. Они имеют запросы вида

db.Single("SELECT private_key/public_key FROM " + myPrefix + "my_keys WHERE block_id = (SELECT max(block_id) FROM " + myPrefix + "my_keys).

SELECT max(block_id) FROM " + myPrefix + "my_keys возвратит у нас 0 и получается запрос

SELECT private_key/public_key FROM " + myPrefix + "my_keys WHERE block_id = 0.

То есть запрос получается неопределенный
На усмотрении движка БД может вернуться как approved запись, так и my_pending, которая имеет невалидный ключ. Чаще видимо возвращается первая запись,

При замене этого запроса на запрос

SELECT private_key/public_key FROM " + myPrefix + "my_keys WHERE status!='my_pending' order by block_id desc limit 0,1

Всякая двусмысленность исчезает и будет возвращаться последний одобренный ключ.

Зацикливание в нащем случае похоже как раз и просиходит при возврашении невалидного ключа в условии content.go

if (string(utils.BinToHex(userPublicKey)) != sessPublicKey && len(myPrivateKey) == 0) || (countUsers > 0 && len(myPrivateKey) > 0 && !bytes.Equal(myPublicKey, []byte(userPublicKey))) {

Похожи запросы с (SELECT max(block_id) FROM " + myPrefix + "my_keys встречаются еще в нескольких местах и по хорошему там тоже нужно исправить для избежания подобных ситуаций.

Я исправил ошибку с зацикливанием. Я меня на тестовом примере зацикливания в этом варианте нет. Там еще нужно было private_key удалять из my_keys, если при автоматическом логине была ошибка .
А по самой причине ошибки при смене ключа пока не стал менять.