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.
This commit is contained in:
Evgenii Stratonikov 2020-03-10 09:54:05 +03:00
parent 4b83e9a5cd
commit 8d73276393
2 changed files with 29 additions and 6 deletions

View file

@ -11,7 +11,10 @@ import (
) )
// Address is a wrapper for Uint160 with flag.Value methods. // 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 // AddressFlag is a flag with type string
type AddressFlag struct { type AddressFlag struct {
@ -27,7 +30,7 @@ var (
// String implements fmt.Stringer interface. // String implements fmt.Stringer interface.
func (a Address) String() string { func (a Address) String() string {
return address.Uint160ToString(util.Uint160(a)) return address.Uint160ToString(a.Value)
} }
// Set implements flag.Value interface. // Set implements flag.Value interface.
@ -36,14 +39,24 @@ func (a *Address) Set(s string) error {
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return cli.NewExitError(err, 1)
} }
*a = Address(addr) a.IsSet = true
a.Value = addr
return nil return nil
} }
// Uint160 casts address to Uint160. // Uint160 casts address to Uint160.
func (a *Address) Uint160() (u util.Uint160) { func (a *Address) Uint160() (u util.Uint160) {
copy(u[:], a[:]) if !a.IsSet {
return // 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 // String returns a readable representation of this value

View file

@ -198,6 +198,9 @@ func claimGas(ctx *cli.Context) error {
defer wall.Close() defer wall.Close()
addrFlag := ctx.Generic("address").(*flags.Address) addrFlag := ctx.Generic("address").(*flags.Address)
if !addrFlag.IsSet {
return cli.NewExitError("address was not provided", 1)
}
scriptHash := addrFlag.Uint160() scriptHash := addrFlag.Uint160()
acc := wall.GetAccount(scriptHash) acc := wall.GetAccount(scriptHash)
if acc == nil { if acc == nil {
@ -395,6 +398,9 @@ func transferAsset(ctx *cli.Context) error {
defer wall.Close() defer wall.Close()
fromFlag := ctx.Generic("from").(*flags.Address) fromFlag := ctx.Generic("from").(*flags.Address)
if !fromFlag.IsSet {
return cli.NewExitError("'from' address was not provided", 1)
}
from := fromFlag.Uint160() from := fromFlag.Uint160()
acc := wall.GetAccount(from) acc := wall.GetAccount(from)
if acc == nil { if acc == nil {
@ -431,7 +437,11 @@ func transferAsset(ctx *cli.Context) error {
return cli.NewExitError(err, 1) 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{ tx.AddOutput(&transaction.Output{
AssetID: asset, AssetID: asset,
Amount: amount, Amount: amount,