Skip to content

Commit

Permalink
Implement bottom up validation (#398)
Browse files Browse the repository at this point in the history
* WIP: Add path validation in config

* Implement bottom up validation

* Fetch single identifier data directly in validation

* Address  PR comments

* Address new PR comments

* Add channel and connection condition

* Fix lint issues
  • Loading branch information
akhilkumarpilli authored Feb 2, 2021
1 parent f992aca commit 1e0ef8a
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 3 deletions.
124 changes: 122 additions & 2 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,17 @@ func cfgFilesAdd(dir string) (cfg *Config, err error) {
}

pthName := strings.Split(f.Name(), ".")[0]
if err = config.ValidatePath(p); err != nil {
fmt.Printf("%s: %s\n", pth, err.Error())
continue
}
if err = cfg.AddPath(pthName, p); err != nil {
fmt.Printf("%s: %s\n", pth, err.Error())
continue
}

// TODO: Do bottom up validation
// For now, we assume that all chain files must have same filename as chain-id
// this is to ensure non-chain files (global config) does not get parsed into chain struct.
// Future work should implement bottom-up validation.
if c.ChainID != pthName {
fmt.Printf("Skipping non chain file: %s\n", f.Name())
continue
Expand Down Expand Up @@ -420,3 +422,121 @@ func overWriteConfig(cmd *cobra.Command, cfg *Config) error {
}
return err
}

// ValidatePath checks that a path is valid
func (c *Config) ValidatePath(p *relayer.Path) (err error) {
if p.Src.Version == "" {
return fmt.Errorf("source must specify a version")
}
if err = c.ValidatePathEnd(p.Src); err != nil {
return err
}
if err = c.ValidatePathEnd(p.Dst); err != nil {
return err
}
if _, err = p.GetStrategy(); err != nil {
return err
}
if p.Src.Order != p.Dst.Order {
return fmt.Errorf("both sides must have same order ('ORDERED' or 'UNORDERED'), got src(%s) and dst(%s)",
p.Src.Order, p.Dst.Order)
}
return nil
}

// ValidatePathEnd validates provided pathend and returns error for invalid identifiers
func (c *Config) ValidatePathEnd(pe *relayer.PathEnd) error {
if err := pe.ValidateBasic(); err != nil {
return err
}

chain, err := c.Chains.Get(pe.ChainID)
if err != nil {
return err
}

height, err := chain.QueryLatestHeight()
if err != nil {
return err
}

if pe.ClientID != "" {
if err := c.ValidateClient(chain, height, pe); err != nil {
return err
}

if pe.ConnectionID != "" {
if err := c.ValidateConnection(chain, height, pe); err != nil {
return err
}

if pe.ChannelID != "" {
if err := c.ValidateChannel(chain, height, pe); err != nil {
return err
}
}
}

if pe.ConnectionID == "" && pe.ChannelID != "" {
return fmt.Errorf("connectionID is not configured for the channel: %s", pe.ChannelID)
}
}

if pe.ClientID == "" && pe.ConnectionID != "" {
return fmt.Errorf("clientID is not configured for the connection: %s", pe.ConnectionID)
}

return nil
}

// ValidateClient validates client id in provided pathend
func (c *Config) ValidateClient(chain *relayer.Chain, height int64, pe *relayer.PathEnd) error {
if err := pe.Vclient(); err != nil {
return err
}

_, err := chain.QueryClientState(height)
if err != nil {
return err
}

return nil
}

// ValidateConnection validates connection id in provided pathend
func (c *Config) ValidateConnection(chain *relayer.Chain, height int64, pe *relayer.PathEnd) error {
if err := pe.Vconn(); err != nil {
return err
}

connection, err := chain.QueryConnection(height)
if err != nil {
return err
}

if connection.Connection.ClientId != pe.ClientID {
return fmt.Errorf("clientID of connection: %s didn't match with provided ClientID", pe.ConnectionID)
}

return nil
}

// ValidateChannel validates channel id in provided pathend
func (c *Config) ValidateChannel(chain *relayer.Chain, height int64, pe *relayer.PathEnd) error {
if err := pe.Vchan(); err != nil {
return err
}

channel, err := chain.QueryChannel(height)
if err != nil {
return err
}

for _, connection := range channel.Channel.ConnectionHops {
if connection == pe.ConnectionID {
return nil
}
}

return fmt.Errorf("connectionID of channel: %s didn't match with provided ConnectionID", pe.ChannelID)
}
29 changes: 29 additions & 0 deletions cmd/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ $ %s pth gen ibc-0 ibc-1 demo-path --unordered false --version ics20-2`, appName
path.GenSrcConnID()
path.GenSrcChanID()
path.GenDstChanID()
if err = config.ValidatePath(path); err != nil {
return err
}
if err = config.Paths.Add(pth, path); err != nil {
return err
}
Expand All @@ -166,6 +169,9 @@ $ %s pth gen ibc-0 ibc-1 demo-path --unordered false --version ics20-2`, appName
path.GenSrcConnID()
path.GenSrcChanID()
path.GenDstChanID()
if err = config.ValidatePath(path); err != nil {
return err
}
if err = config.Paths.Add(pth, path); err != nil {
return err
}
Expand All @@ -177,6 +183,9 @@ $ %s pth gen ibc-0 ibc-1 demo-path --unordered false --version ics20-2`, appName
path.GenSrcConnID()
path.GenSrcChanID()
path.GenDstChanID()
if err = config.ValidatePath(path); err != nil {
return err
}
if err = config.Paths.Add(pth, path); err != nil {
return err
}
Expand Down Expand Up @@ -225,6 +234,9 @@ $ %s pth gen ibc-0 ibc-1 demo-path --unordered false --version ics20-2`, appName
path.GenDstConnID()
path.GenSrcChanID()
path.GenDstChanID()
if err = config.ValidatePath(path); err != nil {
return err
}
if err = config.Paths.Add(pth, path); err != nil {
return err
}
Expand All @@ -236,6 +248,9 @@ $ %s pth gen ibc-0 ibc-1 demo-path --unordered false --version ics20-2`, appName
path.GenDstConnID()
path.GenSrcChanID()
path.GenDstChanID()
if err = config.ValidatePath(path); err != nil {
return err
}
if err = config.Paths.Add(pth, path); err != nil {
return err
}
Expand Down Expand Up @@ -289,6 +304,9 @@ $ %s pth gen ibc-0 ibc-1 demo-path --unordered false --version ics20-2`, appName
path.GenSrcChanID()
path.GenDstChanID()
}
if err = config.ValidatePath(path); err != nil {
return err
}
if err = config.Paths.Add(pth, path); err != nil {
return err
}
Expand All @@ -297,6 +315,9 @@ $ %s pth gen ibc-0 ibc-1 demo-path --unordered false --version ics20-2`, appName
default:
path.GenSrcChanID()
path.GenDstChanID()
if err = config.ValidatePath(path); err != nil {
return err
}
if err = config.Paths.Add(pth, path); err != nil {
return err
}
Expand Down Expand Up @@ -497,6 +518,10 @@ func fileInputPathAdd(file, name string) (cfg *Config, err error) {
return nil, err
}

if err = config.ValidatePath(p); err != nil {
return nil, err
}

if err = config.Paths.Add(name, p); err != nil {
return nil, err
}
Expand Down Expand Up @@ -631,6 +656,10 @@ func userInputPathAdd(src, dst, name string) (*Config, error) {
return nil, err
}

if err = config.ValidatePath(path); err != nil {
return nil, err
}

if err = config.Paths.Add(name, path); err != nil {
return nil, err
}
Expand Down
1 change: 0 additions & 1 deletion relayer/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ func (p Paths) MustGet(name string) *Path {

// Add adds a path by its name
func (p Paths) Add(name string, path *Path) error {
// TODO: Do bottomo up validation of path
if _, found := p[name]; found {
return fmt.Errorf("path with name %s already exists", name)
}
Expand Down

0 comments on commit 1e0ef8a

Please sign in to comment.