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"
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
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()
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)
}
// 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)
}
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")
}
var deleteAccountCmd = &cobra.Command{
- Use: "delete-account <accountID|alias>",
+ 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)
}
{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})},
},
}
}
}
+// 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: