77 "fmt"
88 "math/big"
99 "os"
10- "path/filepath"
1110 "strings"
1211 "time"
1312
@@ -26,53 +25,55 @@ import (
2625 "github.com/urfave/cli"
2726)
2827
29- // destroyNode tears down the deployed darknode by its name.
30- func destroyNode (ctx * cli.Context ) error {
31- force := ctx .Bool ("force" )
32- name := ctx .Args ().First ()
28+ // status represents the registration status of a Darknode.
29+ type status int
3330
34- // Parse the node config
35- nodePath := util .NodePath (name )
36- config , err := darknode .NewConfigFromJSONFile (filepath .Join (nodePath , "config.json" ))
37- if err != nil {
38- return err
39- }
31+ const (
32+ nilStatus status = iota // Either not registered or fully deregistered.
33+ pendingRegistration
34+ registered
35+ pendingDeregistration
36+ notRefunded
37+ )
4038
41- // Connect to Ethereum
42- client , err := connect (config .Network )
43- if err != nil {
44- return err
45- }
46- dnr , err := bindings .NewDarknodeRegistry (config .DarknodeRegistryAddress , client .EthClient ())
47- if err != nil {
48- return err
39+ // err returns the error message of invalid status.
40+ func (s status ) err () string {
41+ switch s {
42+ case pendingRegistration :
43+ return "Darknode is currently pending registration."
44+ case registered :
45+ return "Darknode is still registered."
46+ case pendingDeregistration :
47+ return "Darknode is currently pending deregistration."
48+ case notRefunded :
49+ return "Darknode bond has not been withdrawn."
50+ default :
51+ return ""
4952 }
50- ethAddr := crypto . PubkeyToAddress ( config . Keystore . Ecdsa . PublicKey )
53+ }
5154
52- // Check if the node is registered
53- if err := checkRegistered (dnr , ethAddr ); err != nil {
54- return err
55- }
56- // Check if the node is in pending registration/deregistration stage
57- if err := checkPendingStage (dnr , ethAddr ); err != nil {
58- return err
59- }
60- // Check if the darknode has been refunded
61- context , cancel := context .WithTimeout (context .Background (), 15 * time .Second )
62- defer cancel ()
63- refunded , err := dnr .IsRefunded (& bind.CallOpts {Context : context }, ethAddr )
64- if err != nil {
65- return err
66- }
67- if ! refunded {
68- fmt .Println ("You haven't refund your darknode. Please refund your darknode from the command center" )
69- return nil
70- }
55+ // destroyNode tears down the deployed darknode by its name.
56+ func destroyNode (ctx * cli.Context ) error {
57+ force := ctx .Bool ("force" )
58+ name := ctx .Args ().First ()
59+ path := util .NodePath (name )
7160
72- // Check if user want to process without extra confirmation
61+ // Check node current registration status.
7362 if ! force {
74- fmt .Println ("Do you really want to destroy your darknode? (Yes/No)" )
63+ st , err := nodeStatus (name )
64+ if err != nil {
65+ color .Red ("Failed to get Darknode registration status: %v" , err )
66+ }
67+ switch st {
68+ case pendingRegistration , pendingDeregistration , registered , notRefunded :
69+ color .Red (st .err ())
70+ color .Red ("Please try again once your Darknode has been fully deregistered and refunded." )
71+ return nil
72+ default :
73+ }
7574
75+ // Last time confirm with user.
76+ fmt .Println ("Are you sure you want to destroy your Darknode? (y/N)" )
7677 reader := bufio .NewReader (os .Stdin )
7778 text , _ := reader .ReadString ('\n' )
7879 input := strings .ToLower (strings .TrimSpace (text ))
@@ -81,18 +82,13 @@ func destroyNode(ctx *cli.Context) error {
8182 }
8283 }
8384
84- color .Green ("Back up config..." )
85- backupFolder := filepath .Join (util .Directory , "backup" , name )
86- if err := util .Run ("mkdir" , "-p" , backupFolder ); err != nil {
87- return err
88- }
89- backup := fmt .Sprintf ("cp %v %v" , filepath .Join (nodePath , "config.json" ), backupFolder )
90- if err := util .Run ("bash" , "-c" , backup ); err != nil {
85+ color .Green ("Backing up config..." )
86+ if err := util .BackUpConfig (name ); err != nil {
9187 return err
9288 }
9389
94- color .Green ("Destroying your darknode ..." )
95- destroy := fmt .Sprintf ("cd %v && terraform destroy --force && cd .. && rm -rf %v" , nodePath , name )
90+ color .Green ("Destroying your Darknode ..." )
91+ destroy := fmt .Sprintf ("cd %v && terraform destroy --force && cd .. && rm -rf %v" , path , name )
9692 return util .Run ("bash" , "-c" , destroy )
9793}
9894
@@ -108,7 +104,7 @@ func withdraw(ctx *cli.Context) error {
108104 receiverAddr := common .HexToAddress (withdrawAddress )
109105
110106 // Parse the node config
111- config , err := darknode . NewConfigFromJSONFile ( filepath . Join ( util .NodePath (name ), "config.json" ) )
107+ config , err := util .Config (name )
112108 if err != nil {
113109 return err
114110 }
@@ -180,7 +176,7 @@ func withdraw(ctx *cli.Context) error {
180176 return nil
181177}
182178
183- // transfer ETH to
179+ // transfer ETH to the provided address.
184180func transfer (transactor * bind.TransactOpts , receiver common.Address , amount ethtypes.Amount , client ethclient.Client ) (* types.Transaction , error ) {
185181 bound := bind .NewBoundContract (receiver , abi.ABI {}, nil , client .EthClient (), nil )
186182 transactor .Value = amount .ToBig ()
@@ -200,6 +196,7 @@ func renAddress(network darknode.Network) string {
200196 }
201197}
202198
199+ // connect to Ethereum.
203200func connect (network darknode.Network ) (ethclient.Client , error ) {
204201 logger := logrus .New ()
205202 switch network {
@@ -212,42 +209,64 @@ func connect(network darknode.Network) (ethclient.Client, error) {
212209 }
213210}
214211
215- func checkRegistered (dnr * bindings.DarknodeRegistry , addr common.Address ) error {
212+ // nodeStatus returns the registration status of the darknode with given name.
213+ func nodeStatus (name string ) (status , error ) {
216214 ctx , cancel := context .WithTimeout (context .Background (), 15 * time .Second )
217215 defer cancel ()
216+ config , err := util .Config (name )
217+ if err != nil {
218+ return 0 , err
219+ }
220+ address := crypto .PubkeyToAddress (config .Keystore .Ecdsa .PublicKey )
218221
219- registered , err := dnr .IsRegistered (& bind.CallOpts {Context : ctx }, addr )
222+ // Connect to Ethereum
223+ client , err := connect (config .Network )
220224 if err != nil {
221- return err
225+ return 0 , err
226+ }
227+ dnrAddr , err := config .DnrAddr (client .EthClient ())
228+ if err != nil {
229+ return 0 , err
222230 }
223- if registered {
224- color .Red ("Your node hasn't been deregistered" )
225- color .Red ("Please go to darknode command center to deregister your darknode." )
226- color .Red ("Please try again after you fully deregister your node" )
231+ dnr , err := bindings .NewDarknodeRegistry (dnrAddr , client .EthClient ())
232+ if err != nil {
233+ return 0 , err
227234 }
228- return nil
229- }
230235
231- func checkPendingStage (dnr * bindings.DarknodeRegistry , addr common.Address ) error {
232- reCtx , reCancel := context .WithTimeout (context .Background (), 15 * time .Second )
233- defer reCancel ()
234- pendingRegistration , err := dnr .IsPendingRegistration (& bind.CallOpts {Context : reCtx }, addr )
236+ // Check if node is in pending registration status
237+ pr , err := dnr .IsPendingRegistration (& bind.CallOpts {Context : ctx }, address )
235238 if err != nil {
236- return err
239+ return 0 , err
237240 }
238- if pendingRegistration {
239- return fmt . Errorf ( "your node is currently in pending registration stage, please deregister your node after next epoch shuffle" )
241+ if pr {
242+ return pendingRegistration , nil
240243 }
241244
242- deCtx , deCancel := context .WithTimeout (context .Background (), time .Minute )
243- defer deCancel ()
244- pendingDeregistration , err := dnr .IsPendingDeregistration (& bind.CallOpts {Context : deCtx }, addr )
245+ // Check if node is registered
246+ r , err := dnr .IsRegistered (& bind.CallOpts {Context : ctx }, address )
245247 if err != nil {
246- return err
248+ return 0 , err
247249 }
248- if pendingDeregistration {
249- return fmt . Errorf ( "your node is currently in pending deregistration stage, please wait for next epoch shuffle and try again" )
250+ if r {
251+ return registered , nil
250252 }
251253
252- return nil
254+ // Check if node in pending deregistration status
255+ pd , err := dnr .IsPendingDeregistration (& bind.CallOpts {Context : ctx }, address )
256+ if err != nil {
257+ return 0 , err
258+ }
259+ if pd {
260+ return pendingDeregistration , nil
261+ }
262+
263+ // Check if node has been refunded
264+ refunded , err := dnr .IsRefunded (& bind.CallOpts {Context : ctx }, address )
265+ if err != nil {
266+ return 0 , err
267+ }
268+ if ! refunded {
269+ return notRefunded , nil
270+ }
271+ return nilStatus , nil
253272}
0 commit comments