From 852dcb035f92296f653b2417633be25f54c64a91 Mon Sep 17 00:00:00 2001 From: Chengcheng Zhang <943420582@qq.com> Date: Thu, 15 Nov 2018 15:05:25 +0800 Subject: [PATCH] Dev fix control (#1462) * fix deleteaccount * delete utxo * update * delete tx * add make install * add some functions * update * add DeleteAccout in wallet * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update --- Makefile | 2 +- account/accounts.go | 53 ++++++++++++++++++++++++++++++++++++---- account/accounts_test.go | 4 --- api/accounts.go | 16 ++++++++++-- cmd/bytomcli/commands/account.go | 16 +++++++----- consensus/general.go | 2 ++ wallet/wallet.go | 36 +++++++++++++++++++++++++++ 7 files changed, 111 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index f5f2a759..1e442fe4 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ BYTOMCLI_RELEASE64 := bytomcli-$(VERSION)-$(GOOS)_amd64 BYTOM_RELEASE32 := bytom-$(VERSION)-$(GOOS)_386 BYTOM_RELEASE64 := bytom-$(VERSION)-$(GOOS)_amd64 -all: test target release-all +all: test target release-all install bytomd: @echo "Building bytomd to cmd/bytomd/bytomd" diff --git a/account/accounts.go b/account/accounts.go index 957aad83..6325a662 100644 --- a/account/accounts.go +++ b/account/accounts.go @@ -55,6 +55,7 @@ var ( ErrDeriveRule = errors.New("invalid key derive rule") ErrContractIndex = errors.New("exceed the maximum addresses per account") ErrAccountIndex = errors.New("exceed the maximum accounts per xpub") + ErrFindTransaction = errors.New("no transaction") ) // ContractKey account control promgram store prefix @@ -299,13 +300,55 @@ func (m *Manager) CreateBatchAddresses(accountID string, change bool, stopIndex return nil } -// DeleteAccount deletes the account's ID or alias matching accountInfo. -func (m *Manager) DeleteAccount(aliasOrID string) (err error) { - account := &Account{} - if account, err = m.FindByAlias(aliasOrID); err != nil { - if account, err = m.FindByID(aliasOrID); err != nil { +// deleteAccountControlPrograms deletes control program matching accountID +func (m *Manager) deleteAccountControlPrograms(accountID string) error { + cps, err := m.ListControlProgram() + if err != nil { + return err + } + + var hash common.Hash + for _, cp := range cps { + if cp.AccountID == accountID { + sha3pool.Sum256(hash[:], cp.ControlProgram) + m.db.Delete(ContractKey(hash)) + } + } + return nil +} + +// deleteAccountUtxos deletes utxos matching accountID +func (m *Manager) deleteAccountUtxos(accountID string) error { + accountUtxoIter := m.db.IteratorPrefix([]byte(UTXOPreFix)) + defer accountUtxoIter.Release() + for accountUtxoIter.Next() { + accountUtxo := &UTXO{} + if err := json.Unmarshal(accountUtxoIter.Value(), accountUtxo); err != nil { return err } + + if accountID == accountUtxo.AccountID { + m.db.Delete(StandardUTXOKey(accountUtxo.OutputID)) + } + } + return nil +} + +// DeleteAccount deletes the account's ID or alias matching account ID. +func (m *Manager) DeleteAccount(accountID string) (err error) { + m.accountMu.Lock() + defer m.accountMu.Unlock() + + account, err := m.FindByID(accountID) + if err != nil { + return err + } + + if err := m.deleteAccountControlPrograms(accountID); err != nil { + return err + } + if err := m.deleteAccountUtxos(accountID); err != nil { + return err } m.cacheMu.Lock() diff --git a/account/accounts_test.go b/account/accounts_test.go index 9088be00..7e4137d3 100644 --- a/account/accounts_test.go +++ b/account/accounts_test.go @@ -128,10 +128,6 @@ func TestDeleteAccount(t *testing.T) { testutil.FatalErr(t, err) } - if err = m.DeleteAccount(account1.Alias); err != nil { - testutil.FatalErr(t, err) - } - found, err := m.FindByID(account1.ID) if err != nil { t.Errorf("expected account %v should be deleted", found) diff --git a/api/accounts.go b/api/accounts.go index d8e56618..613215a3 100644 --- a/api/accounts.go +++ b/api/accounts.go @@ -58,10 +58,22 @@ type AccountInfo struct { } // POST /delete-account -func (a *API) deleteAccount(ctx context.Context, in AccountInfo) Response { - if err := a.wallet.AccountMgr.DeleteAccount(in.Info); err != nil { +func (a *API) deleteAccount(ctx context.Context, filter struct { + AccountID string `json:"account_id"` + AccountAlias string `json:"account_alias"` +}) Response { + accountID := filter.AccountID + if filter.AccountAlias != "" { + acc, err := a.wallet.AccountMgr.FindByAlias(filter.AccountAlias) + if err != nil { + return NewErrorResponse(err) + } + accountID = acc.ID + } + if err := a.wallet.DeleteAccount(accountID); err != nil { return NewErrorResponse(err) } + return NewSuccessResponse(nil) } diff --git a/cmd/bytomcli/commands/account.go b/cmd/bytomcli/commands/account.go index 2bb79e90..ac26b7da 100644 --- a/cmd/bytomcli/commands/account.go +++ b/cmd/bytomcli/commands/account.go @@ -21,6 +21,9 @@ func init() { listAccountsCmd.PersistentFlags().StringVar(&accountID, "id", "", "account ID") listAccountsCmd.PersistentFlags().StringVar(&accountAlias, "alias", "", "account alias") + deleteAccountCmd.PersistentFlags().StringVar(&accountID, "id", "", "account ID") + deleteAccountCmd.PersistentFlags().StringVar(&accountAlias, "alias", "", "account alias") + listAddressesCmd.PersistentFlags().StringVar(&accountID, "id", "", "account ID") listAddressesCmd.PersistentFlags().StringVar(&accountAlias, "alias", "", "account alias") @@ -116,15 +119,16 @@ var listAccountsCmd = &cobra.Command{ } var deleteAccountCmd = &cobra.Command{ - Use: "delete-account ", + Use: "delete-account <[accountAlias]|[accountID]>", Short: "Delete the existing account", - Args: cobra.ExactArgs(1), + Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - accountInfo := &struct { - AccountInfo string `json:"account_info"` - }{AccountInfo: args[0]} + var ins = struct { + AccountID string `json:"account_id"` + AccountAlias string `json:"account_alias"` + }{AccountID: accountID, AccountAlias: accountAlias} - if _, exitCode := util.ClientCall("/delete-account", accountInfo); exitCode != util.Success { + if _, exitCode := util.ClientCall("/delete-account", &ins); exitCode != util.Success { os.Exit(exitCode) } diff --git a/consensus/general.go b/consensus/general.go index 51155aad..931db8c9 100644 --- a/consensus/general.go +++ b/consensus/general.go @@ -130,6 +130,8 @@ var TestNetParams = Params{ {10303, bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c})}, {40000, bc.NewHash([32]byte{0x6b, 0x13, 0x9a, 0x5b, 0x76, 0x77, 0x9b, 0xd4, 0x1c, 0xec, 0x53, 0x68, 0x44, 0xbf, 0xf4, 0x48, 0x94, 0x3d, 0x16, 0xe3, 0x9b, 0x2e, 0xe8, 0xa1, 0x0f, 0xa0, 0xbc, 0x7d, 0x2b, 0x17, 0x55, 0xfc})}, {78000, bc.NewHash([32]byte{0xa9, 0x03, 0xc0, 0x0c, 0x62, 0x1a, 0x3d, 0x00, 0x7f, 0xd8, 0x5d, 0x51, 0xba, 0x43, 0xe4, 0xd0, 0xe3, 0xc5, 0xd4, 0x8f, 0x30, 0xb5, 0x5f, 0xa5, 0x77, 0x62, 0xd8, 0x8b, 0x11, 0x81, 0x5f, 0xb4})}, + {82000, bc.NewHash([32]byte{0x56, 0xb1, 0xba, 0x23, 0x69, 0x5c, 0x8f, 0x51, 0x4e, 0x23, 0xc0, 0xae, 0xaa, 0x25, 0x08, 0xc5, 0x85, 0xf3, 0x7c, 0xd1, 0xc6, 0x15, 0xa2, 0x51, 0xda, 0x79, 0x4f, 0x08, 0x13, 0x66, 0xc9, 0x85})}, + {83200, bc.NewHash([32]byte{0xb4, 0x6f, 0xc5, 0xcf, 0xa3, 0x3d, 0xe1, 0x11, 0x71, 0x68, 0x40, 0x68, 0x0c, 0xe7, 0x4c, 0xaf, 0x5a, 0x11, 0xfe, 0x82, 0xbc, 0x36, 0x88, 0x0f, 0xbd, 0x04, 0xf0, 0xc4, 0x86, 0xd4, 0xd6, 0xd5})}, }, } diff --git a/wallet/wallet.go b/wallet/wallet.go index 25f433ac..50c0a184 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -194,6 +194,42 @@ func (w *Wallet) RescanBlocks() { } } +// deleteAccountTxs deletes all txs in wallet +func (w *Wallet) deleteAccountTxs() { + storeBatch := w.DB.NewBatch() + + txIter := w.DB.IteratorPrefix([]byte(TxPrefix)) + defer txIter.Release() + + for txIter.Next() { + storeBatch.Delete(txIter.Key()) + } + + txIndexIter := w.DB.IteratorPrefix([]byte(TxIndexPrefix)) + defer txIndexIter.Release() + + for txIndexIter.Next() { + storeBatch.Delete(txIndexIter.Key()) + } + + storeBatch.Write() +} + +// DeleteAccount deletes account matching accountID, then rescan wallet +func (w *Wallet) DeleteAccount(accountID string) (err error) { + w.rw.Lock() + defer w.rw.Unlock() + + w.deleteAccountTxs() + + if err := w.AccountMgr.DeleteAccount(accountID); err != nil { + return err + } + + w.RescanBlocks() + return nil +} + func (w *Wallet) getRescanNotification() { select { case <-w.rescanCh: -- 2.11.0