fix_: bad node config migration (#6270)

This commit is contained in:
frank 2025-02-18 18:37:59 +08:00 committed by GitHub
parent b2cd7bd8d2
commit 0e94479457
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 170 additions and 11 deletions

View File

@ -390,10 +390,6 @@ func DefaultNodeConfig(installationID string, request *requests.CreateAccount, o
nodeConfig.ShhextConfig.VerifyENSContractAddress = *request.VerifyENSContractAddress
}
if request.NetworkID != nil {
nodeConfig.NetworkID = *request.NetworkID
}
nodeConfig.TorrentConfig = params.TorrentConfig{
Enabled: false,
Port: 0,

View File

@ -30,6 +30,7 @@ import (
"github.com/status-im/status-go/appdatabase"
"github.com/status-im/status-go/centralizedmetrics"
centralizedmetricscommon "github.com/status-im/status-go/centralizedmetrics/common"
d_common "github.com/status-im/status-go/common"
"github.com/status-im/status-go/common/dbsetup"
"github.com/status-im/status-go/connection"
"github.com/status-im/status-go/eth-node/crypto"
@ -579,6 +580,100 @@ func (b *GethStatusBackend) LoginAccount(request *requests.Login) error {
return b.LoggedIn(request.KeyUID, err)
}
// This is a workaround to make user be able to login again, the root cause is where the node config migration
// failed caused by adding new columns to the node config table, it's been fixed in PR: https://github.com/status-im/status-go/pull/6248.
// Details for the issue: it prevent user from login, it happens when old mobile user ignore upgrade the app to the version which introduced the node config migration
// and choose to upgrade a higher version instead, after upgrading, user first attempt to login will fail because the node config migration will fail.
// and second attempt to login will cause an empty node config saved in the db.
func (b *GethStatusBackend) workaroundToFixBadMigration(request *requests.Login) (err error) {
if !d_common.IsMobilePlatform() { // this issue only happens on mobile platform
return nil
}
b.mu.Lock()
defer b.mu.Unlock()
var (
currentConf *params.NodeConfig
defaultNodeConf *params.NodeConfig
)
currentConf, err = nodecfg.GetNodeConfigFromDB(b.appDB)
if err != nil {
return err
}
// check if we saved a empty node config because of node config migration failed
if currentConf.NetworkID == 0 &&
currentConf.KeyStoreDir == "" &&
currentConf.DataDir == "" &&
currentConf.NodeKey == "" {
// check if exist old node config
oldNodeConf := &params.NodeConfig{}
err = b.appDB.QueryRow("SELECT node_config FROM settings WHERE synthetic_id = 'id'").Scan(&sqlite.JSONBlob{Data: oldNodeConf})
if err != nil && err != sql.ErrNoRows {
return err
}
if err == sql.ErrNoRows {
return errors.New("failed to migrate node config as there's no data in settings")
}
// the createAccount contains all the fields that are needed to create the default node config
createAccount := b.convertLoginRequestToAccountRequest(request)
defaultNodeConf, err = DefaultNodeConfig(oldNodeConf.ShhextConfig.InstallationID, createAccount)
if err != nil {
return err
}
b.overridePartialWithOldNodeConfig(defaultNodeConf, oldNodeConf)
var tx *sql.Tx
tx, err = b.appDB.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil {
return err
}
defer func() {
if err == nil {
err = tx.Commit()
return
}
// don't shadow original error
_ = tx.Rollback()
}()
err = nodecfg.SaveConfigWithTx(tx, defaultNodeConf)
}
return nil
}
func (b *GethStatusBackend) overridePartialWithOldNodeConfig(conf *params.NodeConfig, oldNodeConf *params.NodeConfig) {
// rootDataDir should be set by InitializeApplication or UpdateRootDataDir already
conf.RootDataDir = b.rootDataDir
conf.LogEnabled = oldNodeConf.LogEnabled
conf.LogFile = oldNodeConf.LogFile
conf.LogDir = oldNodeConf.LogDir
conf.LogLevel = oldNodeConf.LogLevel
conf.DataDir = oldNodeConf.DataDir
conf.KeyStoreDir = oldNodeConf.KeyStoreDir
conf.NodeKey = oldNodeConf.NodeKey
conf.RegisterTopics = oldNodeConf.RegisterTopics
conf.RequireTopics = oldNodeConf.RequireTopics
}
func (b *GethStatusBackend) convertLoginRequestToAccountRequest(loginRequest *requests.Login) *requests.CreateAccount {
createAccount := &requests.CreateAccount{}
createAccount.WalletSecretsConfig = loginRequest.WalletSecretsConfig
createAccount.StatusProxyEnabled = loginRequest.StatusProxyEnabled
createAccount.WakuV2Nameserver = &loginRequest.WakuV2Nameserver
createAccount.WakuV2LightClient = loginRequest.WakuV2LightClient
createAccount.WakuV2EnableMissingMessageVerification = loginRequest.WakuV2EnableMissingMessageVerification
createAccount.WakuV2EnableStoreConfirmationForMessagesSent = loginRequest.WakuV2EnableStoreConfirmationForMessagesSent
createAccount.TelemetryServerURL = loginRequest.TelemetryServerURL
createAccount.VerifyTransactionURL = loginRequest.VerifyTransactionURL
createAccount.VerifyENSURL = loginRequest.VerifyENSURL
createAccount.VerifyTransactionChainID = loginRequest.VerifyTransactionChainID
createAccount.VerifyENSContractAddress = loginRequest.VerifyENSContractAddress
return createAccount
}
func (b *GethStatusBackend) loginAccount(request *requests.Login) error {
if err := request.Validate(); err != nil {
return err
@ -621,6 +716,11 @@ func (b *GethStatusBackend) loginAccount(request *requests.Login) error {
return errors.Wrap(err, "failed to open database")
}
//relate PR: https://github.com/status-im/status-go/pull/6248
if err := b.workaroundToFixBadMigration(request); err != nil {
return errors.Wrap(err, "failed to workaround bad migration")
}
defaultCfg := &params.NodeConfig{
// why we need this? relate PR: https://github.com/status-im/status-go/pull/4014
KeycardPairingDataFile: DefaultKeycardPairingDataFile,

View File

@ -6,14 +6,18 @@ import (
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
"github.com/status-im/status-go/common"
"github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/t/utils"
)
const (
v1_10_keyUID = "0x88f310d80e3d5821c00714c52bf4fae15f571ba5abae6d804b1e8a9723136a9c"
v1_10_passwd = "0x20756cad9b728c8225fd8cedb6badaf8731e174506950219ea657cd54f35f46c" // #nosec G101
v1_10_srcFolder = "../static/test-mobile-release-1.10.1"
v1_10_keyUID = "0x88f310d80e3d5821c00714c52bf4fae15f571ba5abae6d804b1e8a9723136a9c"
v1_10_passwd = "0x20756cad9b728c8225fd8cedb6badaf8731e174506950219ea657cd54f35f46c" // #nosec G101
v1_10_BeforeUpgradeFolder = "../static/test-mobile-release-1.10.1/before-upgrade-to-v2.30.0"
// This folder is used to test the case where the node config migration failed
// and the user logs in again after the failure
v1_10_AfterUpgradeFolder = "../static/test-mobile-release-1.10.1/after-upgrade-to-v2.30.0"
)
type OldMobileV1_10_UserLoginTest struct {
@ -24,9 +28,6 @@ type OldMobileV1_10_UserLoginTest struct {
func (s *OldMobileV1_10_UserLoginTest) SetupTest() {
utils.Init()
s.tmpdir = s.T().TempDir()
copyDir(v1_10_srcFolder, s.tmpdir, s.T())
var err error
s.logger, err = zap.NewDevelopment()
s.Require().NoError(err)
@ -36,7 +37,10 @@ func TestOldMobileV1_10_UserLogin(t *testing.T) {
suite.Run(t, new(OldMobileV1_10_UserLoginTest))
}
func (s *OldMobileV1_10_UserLoginTest) TestLogin() {
func (s *OldMobileV1_10_UserLoginTest) TestLoginWithSuccessNodeConfigMigration() {
s.tmpdir = s.T().TempDir()
copyDir(v1_10_BeforeUpgradeFolder, s.tmpdir, s.T())
b := NewGethStatusBackend(s.logger)
b.UpdateRootDataDir(s.tmpdir)
s.Require().NoError(b.OpenAccounts())
@ -47,3 +51,27 @@ func (s *OldMobileV1_10_UserLoginTest) TestLogin() {
s.Require().NoError(b.LoginAccount(loginRequest))
s.Require().NoError(b.Logout())
}
// without workaroundToFixBadMigration, this test would login fail
func (s *OldMobileV1_10_UserLoginTest) TestLoginWithFailNodeConfigMigration() {
bkFunc := common.IsMobilePlatform
common.IsMobilePlatform = func() bool {
return true
}
defer func() {
common.IsMobilePlatform = bkFunc
}()
s.tmpdir = s.T().TempDir()
copyDir(v1_10_AfterUpgradeFolder, s.tmpdir, s.T())
b := NewGethStatusBackend(s.logger)
b.UpdateRootDataDir(s.tmpdir)
s.Require().NoError(b.OpenAccounts())
loginRequest := &requests.Login{
KeyUID: v1_10_keyUID,
Password: v1_10_passwd,
}
err := b.LoginAccount(loginRequest)
s.Require().NoError(err)
}

View File

@ -40,6 +40,16 @@ type Login struct {
APIConfig *APIConfig `json:"apiConfig"`
StatusProxyEnabled bool `json:"statusProxyEnabled"`
// Following fields are used for migration from old node config to new one
WakuV2LightClient bool `json:"wakuV2LightClient"`
WakuV2EnableStoreConfirmationForMessagesSent bool `json:"wakuV2EnableStoreConfirmationForMessagesSent"`
WakuV2EnableMissingMessageVerification bool `json:"wakuV2EnableMissingMessageVerification"`
TelemetryServerURL string `json:"telemetryServerURL"`
VerifyTransactionURL *string `json:"verifyTransactionURL"`
VerifyENSURL *string `json:"verifyENSURL"`
VerifyENSContractAddress *string `json:"verifyENSContractAddress"`
VerifyTransactionChainID *int64 `json:"verifyTransactionChainID"`
}
func (c *Login) Validate() error {

View File

@ -0,0 +1,2 @@
The account data files in this directory are generated with android release apk v1.10.1.
It's used to test whether older status-go accounts can log in with the latest version of status-go.

View File

@ -0,0 +1 @@
37d8e2a10dc12253a48ca9fe8af4edd3176b76563b2ce2a17eaa3c65e2b15a35

View File

@ -0,0 +1,8 @@
=============== Jan 10, 2025 (UTC) ===============
08:28:04.874809 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
08:28:04.876561 db@open opening
08:28:04.877163 version@stat F·[] S·0B[] Sc·[]
08:28:04.881631 db@janitor F·2 G·0
08:28:04.881703 db@open done T·5.131458ms
08:45:33.946633 db@close closing
08:45:33.947813 db@close done T·1.201375ms

View File

@ -0,0 +1,8 @@
=============== Jan 10, 2025 (UTC) ===============
08:28:04.869465 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
08:28:04.871618 db@open opening
08:28:04.872157 version@stat F·[] S·0B[] Sc·[]
08:28:04.873259 db@janitor F·2 G·0
08:28:04.873299 db@open done T·1.661375ms
08:45:33.947909 db@close closing
08:45:33.948202 db@close done T·290µs

View File

@ -0,0 +1 @@
{"address":"a64e3fa6f903bcecb15626b86e7ebb23a1f51637","crypto":{"cipher":"aes-128-ctr","ciphertext":"2be636220812a32406bd788693186e4cc10389a6dd0c9219f19c0d8549df29fe","cipherparams":{"iv":"b9bde28266ec3c6cbdd261fa291fc6c7"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"24d55064449be0b55db1540fd617db259ba157633d564929305d32844732e265"},"mac":"97fe060748cc119a9bacb877d614043ee587e672ad3b03243a012e2f508d431a"},"id":"079a7e5f-b2a5-4db5-9609-90559bd4e76d","version":3,"extendedkey":{"cipher":"aes-128-ctr","ciphertext":"9d5b24438b27be2efd7bf124d8a171b7936d1c36ab70ded50e912d8e40719b895538875391963948eaee256c92c4fa78df31b8dc119365698a8a0567c01f218a3cf1959fc4139af53279563816921d9665f7846de14272d3ec31306ffccc6fa9c894843578f7808b0379031572a958","cipherparams":{"iv":"1736cb5848feb3276c1086a6b0ed3a8c"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"5661a7fed8196676e860c67ea8cbd98b23bb43601d4b3145ec8c3272fbb09666"},"mac":"d47edca606e668ddb92135cd14bac6eda65a0207837a2435d621562cd6075f6b"},"subaccountindex":0}

View File

@ -0,0 +1 @@
{"address":"33ec2bc1dafd01868ef846747cc639a22f9f9ac8","crypto":{"cipher":"aes-128-ctr","ciphertext":"3d70719bd93c15c1617c81cacbc50cb2d968b0ec19494711d3a9716493589a06","cipherparams":{"iv":"ad346e2abd8e18877868a27202db56b8"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"e7ec638ee76bd15a8407385f0e0db09e2f543d8fe51224a914d2be05739b53da"},"mac":"eb9c2442ace5cd28b51bf066e6780ab98750a34ad6736f0154ef660ed45ef084"},"id":"7fa6c3fb-c79a-453c-a387-51e44be5ff73","version":3,"extendedkey":{"cipher":"aes-128-ctr","ciphertext":"50fd960987eccef995ab5dba9515254c565690452cae6fc2d4d36fa7ef79487b6e49b6c8b4fd940306c32e47c18beb7b4cf9f43c223808fcc580ec2bc6048397e03d014569e88ea17cc32009761c73d96e1faf2a80388ae4ca6fdd3c39135d42de3e23809e83fc87b8150294ef9ea7","cipherparams":{"iv":"da011707bdfe431903bf2d42ad2a5440"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"b3f7656df7e7bef77f002b5d31a0d0549ffa4139aba108ff855aa66b1301bffd"},"mac":"7444f44a3c9a50c0bf52dba24b1b516c790e6f7b28b718d14540f1dece477862"},"subaccountindex":0}

View File

@ -0,0 +1 @@
{"address":"0e90e6bbe03c68b570c3a12bf327e31d590c262a","crypto":{"cipher":"aes-128-ctr","ciphertext":"c5fedc26b5a36a77dc4406799de1188dd7da6ff7dbda232d312ab098342fdeac","cipherparams":{"iv":"9436848e6e9431f5381a16b059ef674c"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"a88217ef4e823cdbcd08c773dca37a0ac3989729ff75916526a41120a16f81c8"},"mac":"ef9729843b99edbc762c2f19f4af52ea55c7083884ba93ba7727f71f677c4f55"},"id":"14dba39a-2ffe-4f2b-973b-4b7dfcfa33ef","version":3,"extendedkey":{"cipher":"aes-128-ctr","ciphertext":"87e76dd157cd81e134692df6c62159e9c290647fc7cf634b7f7dacff3da0f766c2fe08f96533dd124ed7e9e50ba033b3d4e7f236b95f95a01839a3654b32e562414dc70c006cda5c4f7394bc3b9b3dbde2d36b52a21f77c0de590e22292c310fff1f91d0abdd8453b85ff913f76b99","cipherparams":{"iv":"7699daf7f3f3e924217cabbd454055c6"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"18a0192018134313395f590f2f8e715f54d6680187af59a9de1644a2593b4cba"},"mac":"cb7db464595b921b2f0fb4b158e1aceedef8df0acce51b70b5ea5c4032b4b56a"},"subaccountindex":0}

View File

@ -0,0 +1 @@
{"address":"38fb3454a695aa1ba434604b550d9a439f764346","crypto":{"cipher":"aes-128-ctr","ciphertext":"7a5671cade118faf184a1a162ab906c260f63e7f45ba1a678bec3626b56ac10d","cipherparams":{"iv":"ae5c7a380054eef5ddad4046ca1ade9b"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"b825bebb3977671dd42844dbe6d81984e0e721cb7dd23d444ce392411a2172c7"},"mac":"ad55f72fc4702af1473d7da13e8dd0f69added33412e867818bd289aef503569"},"id":"b49c1e46-cb86-451b-bde7-bb10481c6919","version":3,"extendedkey":{"cipher":"aes-128-ctr","ciphertext":"eb5029c62a9d66bbf15b3c3f12e5d76f676c92cf3a1b33a1413cba72dbfcf4dd093b96eabbf2d8c07fb95a530dc3e78ebef9e0786b9c2fd9bd9d0dbe24c5010d868904b74f8d02e7cd34a37f56195c85cea1566f0e95aaabf24d83ad7b606bce6b0fbabae84898fd3b468bdf0dd067","cipherparams":{"iv":"42bbdebb5b7bb8f6c598ec24f189ab43"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"49271401aedc577b17ef864340782727c642589cb6003421364520d068dd6b0f"},"mac":"490e845666b3e32af69ffd7cd1eb212120f6ee2dfb809f2b679d5415d53d2efc"},"subaccountindex":0}