From 8d73276393109a5169d81b077274b5d0c45532cd Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 10 Mar 2020 09:54:05 +0300 Subject: [PATCH] cli: do not allow default value for an empty address Right now a bizarre error message can occur if an address flag was not set: `wallet contains no account for 'AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM'`. This bug is 10x worse if it occures in `transfer` --from flag. --- cli/flags/address.go | 23 ++++++++++++++++++----- cli/wallet/wallet.go | 12 +++++++++++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/cli/flags/address.go b/cli/flags/address.go index 7468960d1..264c773ee 100644 --- a/cli/flags/address.go +++ b/cli/flags/address.go @@ -11,7 +11,10 @@ import ( ) // Address is a wrapper for Uint160 with flag.Value methods. -type Address util.Uint160 +type Address struct { + IsSet bool + Value util.Uint160 +} // AddressFlag is a flag with type string type AddressFlag struct { @@ -27,7 +30,7 @@ var ( // String implements fmt.Stringer interface. func (a Address) String() string { - return address.Uint160ToString(util.Uint160(a)) + return address.Uint160ToString(a.Value) } // Set implements flag.Value interface. @@ -36,14 +39,24 @@ func (a *Address) Set(s string) error { if err != nil { return cli.NewExitError(err, 1) } - *a = Address(addr) + a.IsSet = true + a.Value = addr return nil } // Uint160 casts address to Uint160. func (a *Address) Uint160() (u util.Uint160) { - copy(u[:], a[:]) - return + if !a.IsSet { + // It is a programmer error to call this method without + // checking if the value was provided. + panic("address was not set") + } + return a.Value +} + +// IsSet checks if flag was set to a non-default value. +func (f AddressFlag) IsSet() bool { + return f.Value.IsSet } // String returns a readable representation of this value diff --git a/cli/wallet/wallet.go b/cli/wallet/wallet.go index 483eb6131..4a0fd7a26 100644 --- a/cli/wallet/wallet.go +++ b/cli/wallet/wallet.go @@ -198,6 +198,9 @@ func claimGas(ctx *cli.Context) error { defer wall.Close() addrFlag := ctx.Generic("address").(*flags.Address) + if !addrFlag.IsSet { + return cli.NewExitError("address was not provided", 1) + } scriptHash := addrFlag.Uint160() acc := wall.GetAccount(scriptHash) if acc == nil { @@ -395,6 +398,9 @@ func transferAsset(ctx *cli.Context) error { defer wall.Close() fromFlag := ctx.Generic("from").(*flags.Address) + if !fromFlag.IsSet { + return cli.NewExitError("'from' address was not provided", 1) + } from := fromFlag.Uint160() acc := wall.GetAccount(from) if acc == nil { @@ -431,7 +437,11 @@ func transferAsset(ctx *cli.Context) error { return cli.NewExitError(err, 1) } - toAddr := ctx.Generic("to").(*flags.Address).Uint160() + toFlag := ctx.Generic("to").(*flags.Address) + if !toFlag.IsSet { + return cli.NewExitError("'to' address was not provided", 1) + } + toAddr := toFlag.Uint160() tx.AddOutput(&transaction.Output{ AssetID: asset, Amount: amount,