message: cron_test integrations to YAML

diff:
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
+- from:
+ uri: "cron:tab"
+ parameters:
+ schedule: "0/1 * * * * ?"
+ steps:
+ - set-header:
+ name: "m"
+ constant: "string!"
+ - set-body:
+ simple: "Magic${header.m}"
+ - to:
+ uri: "log:info"
+ parameters:
+ show-all: "false"

diff:
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
+- route:
+ id: "yaml"
+ from:
+ uri: "quartz:trigger"
+ parameters:
+ cron: "0/1 * * * * ?"
+ steps:
+ - set-header:
+ name: "m"
+ constant: "string!"
+ - set-body:
+ simple: "Magic${header.m}"
+ - to:
+ uri: "log:info"
+ parameters:
+ show-all: "false"

diff:
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
+- route:
+ id: "yaml"
+ from:
+ uri: "timer:tick"
+ parameters:
+ period: "60000"
+ steps:
+ - set-header:
+ name: "m"
+ constant: "string!"
+ - set-body:
+ simple: "Magic${header.m}"
+ - to:
+ uri: "log:info"
+ parameters:
+ show-all: "false"
+
\ No newline at end of file

diff:
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
+- from:
+ uri: "cron:tab"
+ parameters:
+ schedule: "* * * * ?"
+ steps:
+ - set-header:
+ name: "m"
+ constant: "string!"
+ - set-body:
+ simple: "Magic${header.m}"
+ - to:
+ uri: "log:info"
+ parameters:
+ show-all: "false"

original_message: cron_test integrations to YAML


message: Not used resources (integrations) were deleted

change_type: DELETE

diff:
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.apache.camel.builder.RouteBuilder;
-
-public class RestConsumer extends RouteBuilder {
- @Override
- public void configure() throws Exception {
-
- rest("/customers")
- .get("/{name}").to("direct:start");
-
- from("direct:start").log("get ${header.name}").setBody(simple("${header.name} Doe"));
- }
-}

diff:
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-from('timer:tick').to('http:{{serviceName}}/customers/{{name}}')
- .log('${body}')

diff:
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-from('cron:tab?schedule=0/1+*+*+*+*+?')
- .routeId('groovy')
- .setHeader("m").constant("string!")
- .setBody()
- .simple('Magic${header.m}')
- .to('log:info?showAll=false')

diff:
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-from('quartz:trigger?cron=0/1+*+*+*+*+?')
- .routeId('groovy')
- .setHeader("m").constant("string!")
- .setBody()
- .simple('Magic${header.m}')
- .to('log:info?showAll=false')

diff:
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-from('timer:tick?period=60000')
- .routeId('groovy')
- .setHeader("m").constant("string!")
- .setBody()
- .simple('Magic${header.m}')
- .to('log:info?showAll=false')

diff:
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-from('cron:tab?schedule=*+*+*+*+?')
- .routeId('groovy')
- .setHeader("m").constant("string!")
- .setBody()
- .simple('Magic${header.m}')
- .to('log:info?showAll=false')

license: Apache License 2.0

repo: apache/camel-k


change_type: MODIFY

diff:
@@ -43,11 +43,11 @@ func newDescribeIntegrationCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command,
Short: "Describe an Integration",
Long: `Describe an Integration.`,
PreRunE: decode(&options),
- RunE: func(_ *cobra.Command, args []string) error {
- if err := options.validate(args); err != nil {
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if err := options.validate(cmd, args); err != nil {
return err
}
- if err := options.run(args); err != nil {
+ if err := options.run(cmd, args); err != nil {
fmt.Println(err.Error())
}
@@ -65,14 +65,14 @@ type describeIntegrationCommandOptions struct {
showSourceContent bool `mapstructure:"show-source-content"`
}
-func (command *describeIntegrationCommandOptions) validate(args []string) error {
+func (command *describeIntegrationCommandOptions) validate(_ *cobra.Command, args []string) error {
if len(args) != 1 {
return errors.New("describe expects an integration name argument")
}
return nil
}
-func (command *describeIntegrationCommandOptions) run(args []string) error {
+func (command *describeIntegrationCommandOptions) run(cmd *cobra.Command, args []string) error {
c, err := command.GetCmdClient()
if err != nil {
return err
@@ -85,21 +85,21 @@ func (command *describeIntegrationCommandOptions) run(args []string) error {
}
if err := c.Get(command.Context, key, &ctx); err == nil {
- if desc, err := command.describeIntegration(ctx); err == nil {
+ if desc, err := command.describeIntegration(cmd, ctx); err == nil {
fmt.Print(desc)
} else {
fmt.Println(err)
}
} else {
- fmt.Printf("Integration '%s' does not exist.\n", args[0])
+ fmt.Fprintf(cmd.OutOrStdout(), "Integration '%s' does not exist.\n", args[0])
}
return nil
}
-func (command *describeIntegrationCommandOptions) describeIntegration(i v1.Integration) (string, error) {
+func (command *describeIntegrationCommandOptions) describeIntegration(cmd *cobra.Command, i v1.Integration) (string, error) {
return indentedwriter.IndentedString(func(out io.Writer) error {
- w := indentedwriter.NewWriter(out)
+ w := indentedwriter.NewWriter(cmd.OutOrStdout())
describeObjectMeta(w, i.ObjectMeta)

diff:
@@ -42,11 +42,11 @@ func newDescribeKameletCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *des
Short: "Describe a Kamelet",
Long: `Describe a Kamelet.`,
PreRunE: decode(&options),
- RunE: func(_ *cobra.Command, args []string) error {
- if err := options.validate(args); err != nil {
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if err := options.validate(cmd, args); err != nil {
return err
}
- if err := options.run(args); err != nil {
+ if err := options.run(cmd, args); err != nil {
fmt.Println(err.Error())
}
@@ -61,14 +61,14 @@ type describeKameletCommandOptions struct {
*RootCmdOptions
}
-func (command *describeKameletCommandOptions) validate(args []string) error {
+func (command *describeKameletCommandOptions) validate(_ *cobra.Command, args []string) error {
if len(args) != 1 {
return errors.New("describe expects a Kamelet name argument")
}
return nil
}
-func (command *describeKameletCommandOptions) run(args []string) error {
+func (command *describeKameletCommandOptions) run(cmd *cobra.Command, args []string) error {
c, err := command.GetCmdClient()
if err != nil {
return err
@@ -81,7 +81,7 @@ func (command *describeKameletCommandOptions) run(args []string) error {
}
if err := c.Get(command.Context, kameletKey, &kamelet); err == nil {
- if desc, err := command.describeKamelet(kamelet); err == nil {
+ if desc, err := command.describeKamelet(cmd, kamelet); err == nil {
fmt.Print(desc)
} else {
fmt.Println(err)
@@ -93,9 +93,9 @@ func (command *describeKameletCommandOptions) run(args []string) error {
return nil
}
-func (command *describeKameletCommandOptions) describeKamelet(kamelet v1alpha1.Kamelet) (string, error) {
+func (command *describeKameletCommandOptions) describeKamelet(cmd *cobra.Command, kamelet v1alpha1.Kamelet) (string, error) {
return indentedwriter.IndentedString(func(out io.Writer) error {
- w := indentedwriter.NewWriter(out)
+ w := indentedwriter.NewWriter(cmd.OutOrStdout())
describeObjectMeta(w, kamelet.ObjectMeta)

diff:
@@ -41,11 +41,11 @@ func newDescribeKitCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *describ
Short: "Describe an Integration Kit",
Long: `Describe an Integration Kit.`,
PreRunE: decode(&options),
- RunE: func(_ *cobra.Command, args []string) error {
- if err := options.validate(args); err != nil {
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if err := options.validate(cmd, args); err != nil {
return err
}
- if err := options.run(args); err != nil {
+ if err := options.run(cmd, args); err != nil {
fmt.Println(err.Error())
}
@@ -60,14 +60,14 @@ type describeKitCommandOptions struct {
*RootCmdOptions
}
-func (command *describeKitCommandOptions) validate(args []string) error {
+func (command *describeKitCommandOptions) validate(_ *cobra.Command, args []string) error {
if len(args) != 1 {
return errors.New("describe expects a kit name argument")
}
return nil
}
-func (command *describeKitCommandOptions) run(args []string) error {
+func (command *describeKitCommandOptions) run(cmd *cobra.Command, args []string) error {
c, err := command.GetCmdClient()
if err != nil {
return err
@@ -80,7 +80,7 @@ func (command *describeKitCommandOptions) run(args []string) error {
}
if err := c.Get(command.Context, kitKey, kit); err == nil {
- if desc, err := command.describeIntegrationKit(kit); err == nil {
+ if desc, err := command.describeIntegrationKit(cmd, kit); err == nil {
fmt.Print(desc)
} else {
fmt.Println(err)
@@ -92,9 +92,9 @@ func (command *describeKitCommandOptions) run(args []string) error {
return nil
}
-func (command *describeKitCommandOptions) describeIntegrationKit(kit *v1.IntegrationKit) (string, error) {
+func (command *describeKitCommandOptions) describeIntegrationKit(cmd *cobra.Command, kit *v1.IntegrationKit) (string, error) {
return indentedwriter.IndentedString(func(out io.Writer) error {
- w := indentedwriter.NewWriter(out)
+ w := indentedwriter.NewWriter(cmd.OutOrStdout())
describeObjectMeta(w, kit.ObjectMeta)

diff:
@@ -41,11 +41,11 @@ func newDescribePlatformCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *de
Short: "Describe an Integration Platform",
Long: `Describe an Integration Platform.`,
PreRunE: decode(&options),
- RunE: func(_ *cobra.Command, args []string) error {
- if err := options.validate(args); err != nil {
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if err := options.validate(cmd, args); err != nil {
return err
}
- if err := options.run(args); err != nil {
+ if err := options.run(cmd, args); err != nil {
fmt.Println(err.Error())
}
@@ -60,14 +60,14 @@ type describePlatformCommandOptions struct {
*RootCmdOptions
}
-func (command *describePlatformCommandOptions) validate(args []string) error {
+func (command *describePlatformCommandOptions) validate(_ *cobra.Command, args []string) error {
if len(args) != 1 {
return errors.New("describe expects a platform name argument")
}
return nil
}
-func (command *describePlatformCommandOptions) run(args []string) error {
+func (command *describePlatformCommandOptions) run(cmd *cobra.Command, args []string) error {
c, err := command.GetCmdClient()
if err != nil {
return err
@@ -80,21 +80,21 @@ func (command *describePlatformCommandOptions) run(args []string) error {
}
if err := c.Get(command.Context, platformKey, &platform); err == nil {
- if desc, err := command.describeIntegrationPlatform(platform); err == nil {
+ if desc, err := command.describeIntegrationPlatform(cmd, platform); err == nil {
fmt.Print(desc)
} else {
fmt.Println(err)
}
} else {
- fmt.Printf("IntegrationPlatform '%s' does not exist.\n", args[0])
+ fmt.Fprintf(cmd.OutOrStdout(), "IntegrationPlatform '%s' does not exist.\n", args[0])
}
return nil
}
-func (command *describePlatformCommandOptions) describeIntegrationPlatform(platform v1.IntegrationPlatform) (string, error) {
+func (command *describePlatformCommandOptions) describeIntegrationPlatform(cmd *cobra.Command, platform v1.IntegrationPlatform) (string, error) {
return indentedwriter.IndentedString(func(out io.Writer) error {
- w := indentedwriter.NewWriter(out)
+ w := indentedwriter.NewWriter(cmd.OutOrStdout())
describeObjectMeta(w, platform.ObjectMeta)
w.Write(0, "Phase:\t%s\n", platform.Status.Phase)
w.Write(0, "Version:\t%s\n", platform.Status.Version)

diff:
@@ -21,6 +21,7 @@ import (
"bufio"
"context"
"fmt"
+ "io"
"os"
"github.com/spf13/cobra"
@@ -53,7 +54,7 @@ type dumpCmdOptions struct {
LogLines int `mapstructure:"logLines"`
}
-func (o *dumpCmdOptions) dump(_ *cobra.Command, args []string) error {
+func (o *dumpCmdOptions) dump(cmd *cobra.Command, args []string) error {
c, err := o.GetCmdClient()
if err != nil {
return err
@@ -67,12 +68,12 @@ func (o *dumpCmdOptions) dump(_ *cobra.Command, args []string) error {
dumpNamespace(o.Context, c, o.Namespace, writer, o.LogLines)
defer writer.Close()
} else {
- dumpNamespace(o.Context, c, o.Namespace, os.Stdout, o.LogLines)
+ dumpNamespace(o.Context, c, o.Namespace, cmd.OutOrStdout(), o.LogLines)
}
return nil
}
-func dumpNamespace(ctx context.Context, c client.Client, ns string, out *os.File, logLines int) error {
+func dumpNamespace(ctx context.Context, c client.Client, ns string, out io.Writer, logLines int) error {
camelClient, err := versioned.NewForConfig(c.GetConfig())
if err != nil {
@@ -173,13 +174,13 @@ func dumpNamespace(ctx context.Context, c client.Client, ns string, out *os.File
return nil
}
-func dumpConditions(prefix string, conditions []v1.PodCondition, out *os.File) {
+func dumpConditions(prefix string, conditions []v1.PodCondition, out io.Writer) {
for _, cond := range conditions {
fmt.Fprintf(out, "%scondition type=%s, status=%s, reason=%s, message=%q\n", prefix, cond.Type, cond.Status, cond.Reason, cond.Message)
}
}
-func dumpLogs(ctx context.Context, c client.Client, prefix string, ns string, name string, container string, out *os.File, logLines int) error {
+func dumpLogs(ctx context.Context, c client.Client, prefix string, ns string, name string, container string, out io.Writer, logLines int) error {
lines := int64(logLines)
stream, err := c.CoreV1().Pods(ns).GetLogs(name, &v1.PodLogOptions{
Container: container,

diff:
@@ -20,7 +20,6 @@ package cmd
import (
"context"
"fmt"
-
"github.com/Masterminds/semver"
"github.com/spf13/cobra"
@@ -67,36 +66,36 @@ func (o *versionCmdOptions) preRunE(cmd *cobra.Command, args []string) error {
return o.RootCmdOptions.preRun(cmd, args)
}
-func (o *versionCmdOptions) run(_ *cobra.Command, _ []string) error {
+func (o *versionCmdOptions) run(cmd *cobra.Command, _ []string) error {
if o.Operator {
c, err := o.GetCmdClient()
if err != nil {
return err
}
- displayOperatorVersion(o.Context, c, o.Namespace)
+ displayOperatorVersion(cmd, o.Context, c, o.Namespace)
} else {
- displayClientVersion()
+ displayClientVersion(cmd)
}
return nil
}
-func displayClientVersion() {
+func displayClientVersion(cmd *cobra.Command) {
if VersionVariant != "" {
- fmt.Printf("Camel K Client %s %s\n", VersionVariant, defaults.Version)
+ fmt.Fprintf(cmd.OutOrStdout(), "Camel K Client %s %s\n", VersionVariant, defaults.Version)
} else {
- fmt.Printf("Camel K Client %s\n", defaults.Version)
+ fmt.Fprintf(cmd.OutOrStdout(), "Camel K Client %s\n", defaults.Version)
}
}
-func displayOperatorVersion(ctx context.Context, c client.Client, namespace string) {
+func displayOperatorVersion(cmd *cobra.Command, ctx context.Context, c client.Client, namespace string) {
operatorVersion, err := operatorVersion(ctx, c, namespace)
if err != nil {
- fmt.Printf("Unable to retrieve operator version: %s\n", err)
+ fmt.Fprintf(cmd.OutOrStdout(), "Unable to retrieve operator version: %s\n", err)
} else {
if operatorVersion == "" {
- fmt.Printf("Unable to retrieve operator version: The IntegrationPlatform resource hasn't been reconciled yet!")
+ fmt.Fprintf(cmd.OutOrStdout(), "Unable to retrieve operator version: The IntegrationPlatform resource hasn't been reconciled yet!")
} else {
- fmt.Printf("Camel K Operator %s\n", operatorVersion)
+ fmt.Fprintf(cmd.OutOrStdout(), "Camel K Operator %s\n", operatorVersion)
}
}
}

original_message:
Output redirection was fixed for several cobra commands

Fix #2495


message: Fixed: redirecting output to the buffer hangs when big string has to be redirected

diff:
@@ -1644,19 +1644,10 @@ func NewTestNamespace(injectKnativeBroker bool) ctrl.Object {
func GetOutputString(command *cobra.Command) string {
var buf bytes.Buffer
- reader, writer, err := os.Pipe()
- if err != nil {
- panic(err)
- }
- command.SetOut(writer)
+ command.SetOut(&buf)
command.Execute()
- writer.Close()
- defer reader.Close()
-
- buf.ReadFrom(reader)
-
return buf.String()
}


message: Kamel CLI help test was added

change_type: ADD

diff:
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package common
+
+import (
+ "testing"
+
+ . "github.com/onsi/gomega"
+
+ . "github.com/apache/camel-k/e2e/support"
+)
+
+func TestKamelCLIHelp(t *testing.T) {
+ WithNewTestNamespace(t, func(ns string) {
+ t.Run("default help message", func(t *testing.T) {
+ helpMsg := GetOutputString(Kamel("help"))
+ Expect(helpMsg).To(ContainSubstring("Apache Camel K is a lightweight integration platform, born on Kubernetes"))
+ Expect(helpMsg).To(ContainSubstring("Usage:"))
+ Expect(helpMsg).To(ContainSubstring("Available Commands:"))
+ Expect(helpMsg).To(ContainSubstring("Flags:"))
+ })
+
+ t.Run("'get' command help (short flag)", func(t *testing.T) {
+ helpMsg := GetOutputString(Kamel("get", "-h"))
+ Expect(helpMsg).To(ContainSubstring("Get the status of integrations deployed on Kubernetes"))
+ Expect(helpMsg).To(ContainSubstring("Usage:"))
+ Expect(helpMsg).To(ContainSubstring("Flags:"))
+ })
+
+ t.Run("'bind' command help (long flag)", func(t *testing.T) {
+ helpMsg := GetOutputString(Kamel("bind", "--help"))
+ Expect(helpMsg).To(ContainSubstring("Bind Kubernetes resources, such as Kamelets, in an integration flow."))
+ Expect(helpMsg).To(ContainSubstring("kamel bind [source] [sink] ... [flags]"))
+ Expect(helpMsg).To(ContainSubstring("Global Flags:"))
+ })
+ })
+}

original_message: Kamel CLI help test was added


message: Kamel CLI version test was added

diff:
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package common
+
+import (
+ "github.com/apache/camel-k/pkg/util/defaults"
+ "testing"
+
+ . "github.com/onsi/gomega"
+
+ . "github.com/apache/camel-k/e2e/support"
+)
+
+func TestKamelCLIVersion(t *testing.T) {
+ WithNewTestNamespace(t, func(ns string) {
+ t.Run("check version correctness", func(t *testing.T) {
+ version := GetOutputString(Kamel("version"))
+ Expect(version).To(ContainSubstring(defaults.Version))
+ })
+ })
+}

original_message: Kamel CLI version test was added


message: Kamel CLI dump test was added

diff:
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package common
+
+import (
+ v1 "k8s.io/api/core/v1"
+ "testing"
+
+ . "github.com/onsi/gomega"
+
+ . "github.com/apache/camel-k/e2e/support"
+)
+
+func TestKamelCLIDump(t *testing.T) {
+ WithNewTestNamespace(t, func(ns string) {
+ t.Run("dump empty namespace", func(t *testing.T) {
+ dump := GetOutputString(Kamel("dump", "-n", ns))
+
+ Expect(dump).To(ContainSubstring("Found 0 integrations:"))
+ Expect(dump).To(ContainSubstring("Found 0 deployments:"))
+ })
+
+ t.Run("dump non-empty namespace", func(t *testing.T) {
+ Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+ Expect(Kamel("run", "files/yaml.yaml", "-n", ns).Execute()).To(Succeed())
+ Eventually(IntegrationPodPhase(ns, "yaml"), TestTimeoutMedium).Should(Equal(v1.PodRunning))
+ Eventually(IntegrationLogs(ns, "yaml")).Should(ContainSubstring("Magicstring!"))
+
+ dump := GetOutputString(Kamel("dump", "-n", ns))
+
+ Expect(dump).To(ContainSubstring("Found 1 platforms"))
+ Expect(dump).To(ContainSubstring("Found 1 integrations"))
+ Expect(dump).To(ContainSubstring("name: yaml"))
+ Expect(dump).To(ContainSubstring("Magicstring!"))
+
+ Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
+ })
+ })
+}

original_message: Kamel CLI dump test was added


message: updated the disabled linters in alphabetic order

diff:
@@ -40,6 +40,8 @@ linters:
- gofumpt
- gomnd
- gomoddirectives
+ - golint
+ - interfacer
- ireturn
- lll
- maligned
@@ -50,12 +52,13 @@ linters:
- paralleltest
- tagliatelle
- tenv
+ - scopelint
- testpackage
- varnamelen
- whitespace
- wrapcheck
- wsl
- interfacer
- - scopelint
- - golint
+
+


message: added a trait example for services

diff:
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//kamel run --trait service.enabled=true
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.example.MyClass;
+
+public class Classpath extends RouteBuilder {
+ @Override
+ public void configure() throws Exception {
+ from("timer:tick")
+ .log(MyClass.sayHello());
+ }
+}
\ No newline at end of file

original_message: added a trait example for services


message: updated service to use a nodeport

diff:
* limitations under the License.
*/
-//kamel run --trait service.enabled=true
+//
+// To run this integrations use:
+//
+// kamel run service.java --trait service.enabled=true\
+// --trait service.node-port=true
+//
+import org.apache.camel.Exchange;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.example.MyClass;
-
-public class Classpath extends RouteBuilder {
+public class RestDSL extends org.apache.camel.builder.RouteBuilder {
@Override
public void configure() throws Exception {
- from("timer:tick")
- .log(MyClass.sayHello());
+ rest()
+ .get("/hello")
+ .to("direct:hello");
+
+ from("direct:hello")
+ .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
+ .transform().simple("Hello World");
}
}

original_message: updated service to use a nodeport


message: added a readme, second example and changed first example file name

diff:
+# SERVICE EXAMPLE
+
+This folder contains examples of how to use a `trait service`. You can use them to learn more about how to enable services for integrations deployed on the cluster.
+
+To access integration outside the cluster you can enable a nodePort when you deploy integration. An example is `./RestDSL.java.`
+
+You can also optionally decide to just go with the default clusterIP if you do not want your integration to be directly exposed to the outside world. An example of this use case is `./RestDSL2.java`
\ No newline at end of file

change_type: RENAME

diff:
//
// To run this integrations use:
-//
-// kamel run service.java --trait service.enabled=true\
+// kamel run RestDSL.java --trait service.enabled=true\
// --trait service.node-port=true
//
import org.apache.camel.Exchange;

diff:
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// To run this integrations use:
+// kamel run RestDSL2.java --trait service.enabled=true
+//
+import org.apache.camel.Exchange;
+
+public class RestDSL extends org.apache.camel.builder.RouteBuilder {
+ @Override
+ public void configure() throws Exception {
+ rest()
+ .get("/hello")
+ .to("direct:hello");
+
+ from("direct:hello")
+ .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
+ .transform().simple("Hello World");
+ }
+}


message: changed class name to file name

diff:
//
import org.apache.camel.Exchange;
-public class RestDSL extends org.apache.camel.builder.RouteBuilder {
+public class RestDSL2 extends org.apache.camel.builder.RouteBuilder {
@Override
public void configure() throws Exception {
rest()

original_message: changed class name to file name


message: added a file-config doc

diff:
+= File Based Configuration
+
+File-based configuration is used to set command flags. Flag values do not need to be entered on a regular basis. The file is read on Kamel startup and the flags are set accordingly.
+
+To configure this flag, create a file named kamel-config.yaml on the same directory as your integration. The file must contain a yaml structure as shown in ./kamel-config.yaml.
\ No newline at end of file

original_message: added a file-config doc


message: added file config example. Linked the example in navigation.

diff:
*** xref:installation/advanced/multi.adoc[Multiple Operators]
* Command Line Interface
** xref:cli/cli.adoc[Kamel CLI]
+** xref:cli/file-based-config.adoc[File-based Config]
** xref:cli/modeline.adoc[Modeline]
* xref:running/running.adoc[Run an Integration]
** xref:running/dev-mode.adoc[Developer mode]

diff:
File-based configuration is used to set command flags. Flag values do not need to be entered on a regular basis. The file is read on Kamel startup and the flags are set accordingly.
-To configure this flag, create a file named kamel-config.yaml on the same directory as your integration. The file must contain a yaml structure as shown in ./kamel-config.yaml.
\ No newline at end of file
+The file's default name is `kamel-config.yaml` . Which should be placed in either of this directory structure:
+
+ - `~/.kamel/`
+ - `./.kamel/`
+ - `.`
+
+it can be overriden by setting an env value `KAMEL_CONFIG_NAME` to file path.
+
+
+To configure this flag, create a file named kamel-config.yaml on the same directory as your integration. The file must contain a yaml structure as shown below:
+
+.Kamel-config.yaml
+
+```yaml
+kamel:
+ install:
+ namespace: kamel
+ healthPort: 8081
+ monitoringPort: 8082
+```


message: corrected typographical error

diff:
@@ -8,7 +8,7 @@ The file's default name is `kamel-config.yaml` . Which should be placed in eithe
- `./.kamel/`
- `.`
-it can be overriden by setting an env value `KAMEL_CONFIG_NAME` to file path.
+it can be overridden by setting an env value `KAMEL_CONFIG_NAME` to file path.
To configure this flag, create a file named kamel-config.yaml on the same directory as your integration. The file must contain a yaml structure as shown below:

original_message: corrected typographical error


message: fixed logic for flags: properties, cm and secrets

diff:
@@ -146,28 +146,20 @@ func (command *kitCreateCommandOptions) run(cmd *cobra.Command, args []string) e
}
}
- for _, item := range command.Properties {
- kit.Spec.Configuration = append(kit.Spec.Configuration, v1.ConfigurationSpec{
- Type: "property",
- Value: item,
- })
- }
- for _, item := range command.Configmaps {
- kit.Spec.Configuration = append(kit.Spec.Configuration, v1.ConfigurationSpec{
- Type: "configmap",
- Value: item,
- })
- }
- for _, item := range command.Secrets {
- kit.Spec.Configuration = append(kit.Spec.Configuration, v1.ConfigurationSpec{
- Type: "secret",
- Value: item,
- })
+if err := command.parseAndConvertToTrait(command.Properties, "camel.properties"); err != nil {
+ return err
}
- if err := command.configureTraits(kit, command.Traits, catalog); err != nil {
+
+if err := command.parseAndConvertToTrait(command.Configmaps, "mount.config"); err != nil {
return err
}
+if err := command.parseAndConvertToTrait(command.Secrets, "mount.config"); err != nil {
+ return err
+}
+if err := command.configureTraits(kit, command.Traits, catalog); err != nil {
+return err
+}
existed := false
err = c.Create(command.Context, kit)
if err != nil && k8serrors.IsAlreadyExists(err) {
@@ -206,3 +198,10 @@ func (*kitCreateCommandOptions) configureTraits(kit *v1.IntegrationKit, options
return nil
}
+func (command *kitCreateCommandOptions) parseAndConvertToTrait(params []string, traitParam string, ) error {
+ for _, param := range params {
+ command.Traits = append(command.Traits, convertToTrait(param, traitParam))
+ }
+
+ return nil
+}
\ No newline at end of file


message: formatted code using gofmt

diff:
@@ -198,7 +198,7 @@ func (*kitCreateCommandOptions) configureTraits(kit *v1.IntegrationKit, options
return nil
}
-func (command *kitCreateCommandOptions) parseAndConvertToTrait(params []string, traitParam string, ) error {
+func (command *kitCreateCommandOptions) parseAndConvertToTrait(params []string, traitParam string) error {
for _, param := range params {
command.Traits = append(command.Traits, convertToTrait(param, traitParam))
}

original_message: formatted code using gofmt


message: added logging traits documentation

diff:
+# Logging Trait
+
+This type of trait tells us what is going on in a running integration pod. It does this by printing logs out to the standard output.
+
+Logs are enabled by default on an integration. Just run this example:
+
+ $kamel run logging.java
+
+ $kamel logs logging
+
+Or you can instead get the pod name and print its logs using kubectl:
+
+ $kubectl get pods
+
+ $kubecttl logs <pod name>
+
+You can configure the log output with the `logging traits` flag:
+
+Property | Type | Description
+---|---|---
+logging.enabled | boolean| We can set to false to disable logging
+logging.color | boolean| makes logging output colorful. This makes skimming through the logs easier.
+logging.json | boolean | Makes logs output to be in json format. We can use tools like `jq` to manipulate output.
+logging.json-pretty-print | boolean | It's like using an in built `jq` to print our json output.
+logging.level | string | This is just a verbosity level settings. We can just use `info`
+
+for more traits options see this [Link.](https://camel.apache.org/camel-k/next/traits/logging.html).
+
+manual log setting example using `logging trait`:
+
+ $kamel run ./logging.java --trait logging.enabled=true --trait logging.json=true --trait logging.level=info
+
+The output of this result would give this:
+- Logging would be enabled, but there would be no colors for easy skimming.
+- You would need to use your own jq to pretty print and parse the json output.
+
+**Image example**
+![json](interface/json.png)
+
+
+## using modeline
+An example of using a `modeline` to set the `logging traits` :
+
+ $kamel run ./loggingModeline.java
+

diff: Binary files /dev/null and b/examples/traits/logging/interface/json.png differ

diff:
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// kamel run ./logging.java --trait logging.enabled=true \
+// --trait logging.json=true --trait logging.level=info
+import org.apache.camel.Exchange;
+
+public class RestDSL extends org.apache.camel.builder.RouteBuilder {
+ @Override
+ public void configure() throws Exception {
+ rest()
+ .get("/hello")
+ .to("direct:hello");
+
+ from("direct:hello")
+ .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
+ .transform().simple("Hello World");
+ }
+}

diff:
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// camel-k: traits=logging.enabled=true trait=logging.json=true trait=logging.level=info
+
+import org.apache.camel.Exchange;
+
+public class RestDSL extends org.apache.camel.builder.RouteBuilder {
+ @Override
+ public void configure() throws Exception {
+ rest()
+ .get("/hello")
+ .to("direct:hello");
+
+ from("direct:hello")
+ .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
+ .transform().simple("Hello World");
+ }
+}

original_message: added logging traits documentation


message: renamed files, removed image, added a log output to readme

diff:
// --trait logging.json=true --trait logging.level=info
import org.apache.camel.Exchange;
-public class RestDSL extends org.apache.camel.builder.RouteBuilder {
+public class Logging extends org.apache.camel.builder.RouteBuilder {
@Override
public void configure() throws Exception {
rest()

diff:
import org.apache.camel.Exchange;
-public class RestDSL extends org.apache.camel.builder.RouteBuilder {
+public class LoggingModeline extends org.apache.camel.builder.RouteBuilder {
@Override
public void configure() throws Exception {
rest()

diff:
@@ -30,14 +30,19 @@ manual log setting example using `logging trait`:
$kamel run ./logging.java --trait logging.enabled=true --trait logging.json=true --trait logging.level=info
-The output of this result would give this:
-- Logging would be enabled, but there would be no colors for easy skimming.
-- You would need to use your own jq to pretty print and parse the json output.
+**Output**
-**Image example**
-![json](interface/json.png)
+The output of this result would give this:
+```
+[2] {"timestamp":"2022-04-24T22:50:06.303Z","sequence":183,"loggerClassName":"org.slf4j.impl.Slf4jLogger","loggerName":"org.apache.camel.impl.engine.AbstractCamelContext","level":"INFO","message":"Apache Camel 3.14.1 (camel-1) started in 352ms (build:0ms init:293ms start:59ms)","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"rest-dsl-56668cc6dc-9zz7r","processName":"io.quarkus.bootstrap.runner.QuarkusEntryPoint","processId":1}
+[2] {"timestamp":"2022-04-24T22:50:06.835Z","sequence":184,"loggerClassName":"org.jboss.logging.Logger","loggerName":"io.quarkus","level":"INFO","message":"camel-k-integration 1.8.2 on JVM (powered by Quarkus 2.7.0.Final) started in 14.348s. Listening on: http://0.0.0.0:8080","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"rest-dsl-56668cc6dc-9zz7r","processName":"io.quarkus.bootstrap.runner.QuarkusEntryPoint","processId":1}
+[2] {"timestamp":"2022-04-24T22:50:06.842Z","sequence":185,"loggerClassName":"org.jboss.logging.Logger","loggerName":"io.quarkus","level":"INFO","message":"Profile prod activated. ","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"rest-dsl-56668cc6dc-9zz7r","processName":"io.quarkus.bootstrap.runner.QuarkusEntryPoint","processId":1}
+[2] {"timestamp":"2022-04-24T22:50:06.842Z","sequence":186,"loggerClassName":"org.jboss.logging.Logger","loggerName":"io.quarkus","level":"INFO","message":"Installed features: [camel-attachments, camel-bean, camel-core, camel-direct, camel-java-joor-dsl, camel-k-core, camel-k-runtime, camel-platform-http, camel-rest, cdi, smallrye-context-propagation, vertx]","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"rest-dsl-56668cc6dc-9zz7r","processName":"io.quarkus.bootstrap.runner.QuarkusEntryPoint","processId":1}
+```
+- Logging would be enabled, and it's output would be in josn. But, there would be no colors for easy skimming.
+- You would need to use your own jq to pretty print and parse the json output.
## using modeline
An example of using a `modeline` to set the `logging traits` :

diff: Binary files a/examples/traits/logging/interface/json.png and /dev/null differ


message: fixed typo error

diff:
*/
//
-// kamel run ./logging.java --trait logging.enabled=true \
+// kamel run ./Logging.java --trait logging.enabled=true \
// --trait logging.json=true --trait logging.level=info
import org.apache.camel.Exchange;

diff:
@@ -43,7 +43,7 @@ The output of this result would give this:
```
- Logging would be enabled, and it's output would be in josn. But, there would be no colors for easy skimming.
- You would need to use your own jq to pretty print and parse the json output.
-## using modeline
+## Using modeline
An example of using a `modeline` to set the `logging traits` :
$ kamel run ./loggingModeline.java

original_message: fixed typo error


message: Move installation instructions into separate document

diff:
+# 1. Installation via Vagrant
+Ensure that Vagrant installed on your local machine
+
+Create a directory and the following Vagrantfile:
+```
+Vagrant.configure("2") do |config|
+ config.vm.box = "ubuntu/xenial64"
+ config.vm.provision "shell", path: "bootstrap.sh"
+ config.vm.provider "virtualbox" do |v|https://appear.in/horde-omisego
+ v.memory = 4096
+ v.cpus = 2
+ end
+end
+```
+
+In the same directory Create a bash file name: bootstrap.sh with the contents of
+https://gist.github.com/Pongch/b38bf178ee9f14dd31cd05fb34e96dce
+
+Run:
+```
+vagrant up --provision
+```
+
+Wait a few minutes for all the dependencies to finish installing
+
+SSH into vagrant:
+```
+vagrant ssh
+```
+
+Set ENVs to compile
+```
+source DEV/bin/activate
+export LC_ALL=C.UTF-8
+export LANG=C.UTF-8
+python3 -m solc.install v0.4.18
+export SOLC_BINARY=/home/vagrant/.py-solc/solc-v0.4.18/bin/solc
+```
+
+Get the code and pull elixir dependencies
+```
+git clone https://github.com/omisego/omisego
+cd omisego
+HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix deps.get
+
+compile and test
+mix test --no-start
+```
+
+# 2. Full installation
+
+**NOTE**: Currently the child chain server and watcher are bundled within a single umbrella app.
+
+Only **Linux** platforms are supported now. These instructions have been tested on a fresh Linode 2048 instance with Ubuntu 16.04.
+
+## Prerequisites
+* Elixir
+* Erlang OTP 20
+* Python '>=3.5, <4'
+* solc 0.4.24
+
+<!-- - Install [Elixir](http://elixir-lang.github.io/install.html#unix-and-unix-like).
+ **OTP 20 is required**, meaning that on Ubuntu, you should modify steps in the linked instructions:
+ `sudo apt install esl-erlang=1:20.3.6`
+
+ - Install or provide access to an Ethereum node (e.g. [geth](https://github.com/ethereum/go-ethereum/wiki/geth))
+ - If required, install the following packages:
+ `sudo apt-get install build-essential autoconf libtool libgmp3-dev` -->
+
+## Install prerequisite packages
+```
+sudo apt-get update
+sudo apt-get -y install build-essential autoconf libtool libgmp3-dev libssl-dev
+```
+
+## Install Erlang OTP 20
+**TODO**: This step is only required until we migrate to OTP 21 in OMG-181
+
+Add the Erlang Solutions repo
+```
+wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo dpkg -i erlang-solutions_1.0_all.deb
+sudo apt-get update
+sudo apt-get install -y esl-erlang=1:20.3.6
+```
+
+## Install Elixir
+```
+sudo apt-get -y install elixir
+```
+
+## Install Geth
+```
+sudo apt-get install -y software-properties-common
+sudo add-apt-repository -y ppa:ethereum/ethereum
+sudo apt-get update
+sudo apt-get -y install geth
+```
+
+## Install pip3
+```
+sudo apt-get -y install python3-pip
+```
+
+## (optional) Install virtualenv
+This step is optional but recommended to isolate the python environment. [Ref](https://gist.github.com/IamAdiSri/a379c36b70044725a85a1216e7ee9a46)
+```
+sudo pip3 install virtualenv
+virtualenv DEV
+cd DEV
+source bin/activate
+```
+
+## Install populus
+[Ref](https://github.com/ethereum/populus/issues/450)
+```
+pip3 install populus
+pip3 install eth-utils==0.8.1 web3==3.16.5
+```
+If an error is raised when installing the specific version of `eth-utils`, the error may be ignored for the purposes of this installation.
+
+## Install solc 0.4.24
+Note that solc 0.4.24 is required
+```
+python3 -m solc.install v0.4.24
+```
+
+## Install rebar
+```
+mix do local.hex --force, local.rebar --force
+```
+## Clone repo and build
+```
+# solc in the path is ignored. Explicitly specify path to binary
+Export SOLC_BINARY=~/.py-solc/solc-v0.4.18/bin/solc
+
+# populus requires character encoding to be set
+export LC_ALL=C.UTF-8
+export LANG=C.UTF-8
+
+git clone https://github.com/omisego/omisego
+cd omisego
+mix deps.get
+```
+
+## Check this works!
+For a quick test (with no integration tests)
+```
+mix test --no-start
+```
+
+To run integration tests (requires compiling contracts)
+```
+mix test --no-start --only integration
+```

repo: omgnetwork/elixir-omg


message: Typo and minor updates

diff:
# 1. Installation via Vagrant
-Ensure that Vagrant installed on your local machine
+## Prerequisites
+* Ensure that [Vagrant](https://www.vagrantup.com/) installed on your local machine
Create a directory and the following Vagrantfile:
```
@@ -13,7 +14,7 @@ Vagrant.configure("2") do |config|
end
```
-In the same directory Create a bash file name: bootstrap.sh with the contents of
+In the same directory, create a bash file named `bootstrap.sh` with the following contents
https://gist.github.com/Pongch/b38bf178ee9f14dd31cd05fb34e96dce
Run:
@@ -59,14 +60,6 @@ Only **Linux** platforms are supported now. These instructions have been tested
* Python '>=3.5, <4'
* solc 0.4.24
-<!-- - Install [Elixir](http://elixir-lang.github.io/install.html#unix-and-unix-like).
- **OTP 20 is required**, meaning that on Ubuntu, you should modify steps in the linked instructions:
- `sudo apt install esl-erlang=1:20.3.6`
-
- - Install or provide access to an Ethereum node (e.g. [geth](https://github.com/ethereum/go-ethereum/wiki/geth))
- - If required, install the following packages:
- `sudo apt-get install build-essential autoconf libtool libgmp3-dev` -->
-
## Install prerequisite packages
```
sudo apt-get update

original_message: Typo and minor updates


message: Add first version of troubleshooting guide

diff:
+# Troubleshooting
+## Could not compile dependency :plasma_mvp_contracts
+Ensure that the environment variable SOLC_BINARY is set:
+```
+export SOLC_BINARY=/home/j/.py-solc/solc-v0.4.18/bin/solc
+```
+
+## Configuring the omisego_eth app fails with error
+```
+** (MatchError) no match of right hand side value: {:error, :econnrefused}
+ lib/eth/dev_helpers.ex:44: OmiseGO.Eth.DevHelpers.create_and_fund_authority_addr/0
+ lib/eth/dev_helpers.ex:11: OmiseGO.Eth.DevHelpers.prepare_env!/1
+ (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
+ (stdlib) erl_eval.erl:878: :erl_eval.expr_list/6
+ (stdlib) erl_eval.erl:404: :erl_eval.expr/5
+ (elixir) lib/code.ex:192: Code.eval_string/3
+ (elixir) lib/enum.ex:737: Enum."-each/2-lists^foreach/1-0-"/2
+ (elixir) lib/enum.ex:737: Enum.each/2
+ (mix) lib/mix/tasks/run.ex:132: Mix.Tasks.Run.run/5
+ (mix) lib/mix/tasks/run.ex:76: Mix.Tasks.Run.run/1
+ (mix) lib/mix/task.ex:314: Mix.Task.run_task/3
+ (mix) lib/mix/cli.ex:80: Mix.CLI.run_task/2
+ (elixir) lib/code.ex:677: Code.require_file/2
+```
+
+Answer: Ensure that the dev Ethereum instance is running: geth
+
+## Error starting child chain server
+```
+** (Mix) Could not start application omisego_api: OmiseGO.API.Application.start(:normal, []) returned an error: shutdown: failed to start child: OmiseGO.API.BlockQueue.Server
+ ** (EXIT) an exception was raised:
+ ** (MatchError) no match of right hand side value: {:error, :mined_blknum_not_found_in_db}
+ (omisego_api) lib/block_queue.ex:78: OmiseGO.API.BlockQueue.Server.init/1
+ (stdlib) gen_server.erl:365: :gen_server.init_it/2
+ (stdlib) gen_server.erl:333: :gen_server.init_it/6
+ (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
+```
+
+Answer:
+rm -rf ~/.omisego
+
+## Error starting child chain server
+```
+22:44:32.024 [info] Started BlockQueue
+22:44:32.068 [error] GenServer OmiseGO.API.BlockQueue.Server terminating
+** (CaseClauseError) no case clause matching: {:error, %{"code" => -32000, "message" => "authentication needed: password or unlock"}}
+ (omisego_api) lib/block_queue.ex:139: OmiseGO.API.BlockQueue.Server.submit/1
+ (elixir) lib/enum.ex:737: Enum."-each/2-lists^foreach/1-0-"/2
+ (elixir) lib/enum.ex:737: Enum.each/2
+ (omisego_api) lib/block_queue.ex:101: OmiseGO.API.BlockQueue.Server.handle_info/2
+ (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
+ (stdlib) gen_server.erl:686: :gen_server.handle_msg/6
+ (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
+Last message: :check_mined_child_head
+```
+Answer:
+rm -rf ~/.geth
+rm -rf ~/.omisego
+
+## Error Starting child chain server
+```
+** (Mix) Could not start application omisego_api: OmiseGO.API.Application.start(:normal, []) returned an error: shutdown: failed to start child: OmiseGO.API.State
+ ** (EXIT) an exception was raised:
+ ** (ArithmeticError) bad argument in arithmetic expression
+ (omisego_api) lib/state/core.ex:30: OmiseGO.API.State.Core.extract_initial_state/4
+ (omisego_api) lib/state.ex:70: OmiseGO.API.State.init/1
+ (stdlib) gen_server.erl:365: :gen_server.init_it/2mix d
+ (stdlib) gen_server.erl:333: :gen_server.init_it/6
+ (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
+```
+Answer:
+Child chain database not initialized yet
+
+## To compile or recompile the contracts
+```
+cd ~/omisego/populus
+mix deps.compile plasma_mvp_contracts
+```
+
+## To re-activate the virtualenv
+```
+cd ~
+source DEV/bin/activate
+```


message: Add overview diagram and short explanation

diff: Binary files /dev/null and b/assets/OMG-network-eWallet.jpg differ

diff:
@@ -52,6 +52,8 @@ mix test --no-start
**NOTE**: Currently the child chain server and watcher are bundled within a single umbrella app.
+**TODO** hex-ify the package.
+
Only **Linux** platforms are supported now. These instructions have been tested on a fresh Linode 2048 instance with Ubuntu 16.04.
## Prerequisites


message: Include architecture overview diagram

old_path: assets/architecture overview.png

new_path: assets/architecture overview.png

diff: Binary files /dev/null and b/assets/architecture overview.png differ

diff:
# Architecture
-This is a high-level rundown of the architecture of `OmiseGO` apps.
+This is a high-level rundown of the architecture of the `OmiseGO` apps.
-For an even higher-level rundown of various pieces, where this umbrella app fits in, see **[High-level diagram](https://docs.google.com/drawings/d/1wvyQPKrrBnjlA1BfhMYxHFXbbn0ixL5WaSavGTaj14s/edit)**.
-**NOTE** only use the high-level diagram to get a vague idea, meaning of boxes/arrows is very imprecise.
+The below diagram demonstrates the various pieces and where this umbrella app fits in.
+
+![high level architecture overview diagram](../assets/architecture overview.png)
+
+**NOTE** only use the high-level diagram to get a vague idea, meaning of boxes/arrows may be imprecise.
## Interactions

original_message: Include architecture overview diagram


message: Note on how to configure watcher

diff:
@@ -8,6 +8,21 @@ For the responsibilities and design of the watcher see [Tesuji Plasma Blockchain
**TODO** write proper README after we distill how to run this.
+## Configure the `omisego_watcher` app
+Create another copy of the configuration file. The values for `contract_addr`, `txhash_contract` and `authority_addr` should be the same as the `omisego_api` app. However, `leveldb_path` should be set to a different directory than `omisego_watcher`.
+
+The confiration file should look something like this:
+
+```
+use Mix.Config
+config :omisego_eth,
+ contract_addr: "0x005f49af1af9eee6da214e768683e1cc8ab222ac",
+ txhash_contract: "0x3afd2c1b48eaa3100823de1924d42bd48ee25db1fd497998158f903b6a841e92",
+ authority_addr: "0x5c1a5e5d94067c51ec51c6c00416da56aac6b9a3"
+ leveldb_path: Path.join([System.get_env("HOME"), "~/omisego/data_watcher"])
+
+```
+
## Setting up and running the watcher
```

original_message: Note on how to configure watcher


message: Populus install

diff:
@@ -65,7 +65,7 @@ Only **Linux** platforms are supported now. These instructions have been tested
## Install prerequisite packages
```
sudo apt-get update
-sudo apt-get -y install build-essential autoconf libtool libgmp3-dev libssl-dev
+sudo apt-get -y install build-essential autoconf libtool libgmp3-dev libssl-dev wget git
```
## Install Erlang OTP 20
@@ -101,13 +101,13 @@ This step is optional but recommended to isolate the python environment. [Ref](h
```
sudo pip3 install virtualenv
virtualenv DEV
-cd DEV
-source bin/activate
+source DEV/bin/activate
```
## Install populus
[Ref](../populus/README.md)
```
+wget https://github.com/omisego/omisego/blob/develop/populus/requirements.txt
pip3 install -r populus/requirements.txt
```
If an error is raised when installing the specific version of `eth-utils`, the error may be ignored for the purposes of this installation.
@@ -123,9 +123,6 @@ mix do local.hex --force, local.rebar --force
```
## Clone repo and build
```
-# solc in the path is ignored. Explicitly specify path to binary
-Export SOLC_BINARY=~/.py-solc/solc-v0.4.18/bin/solc
-
# populus requires character encoding to be set
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
@@ -145,3 +142,6 @@ To run integration tests (requires compiling contracts)
```
mix test --no-start --only integration
```
+
+## Next steps
+Follow the README steps for the [child chain server](../apps/omisego_api/README.md).

original_message: Populus install


message: Move architecture diagram to under docs/assets

diff:
@@ -4,7 +4,7 @@ This is a high-level rundown of the architecture of the `OmiseGO` apps.
The below diagram demonstrates the various pieces and where this umbrella app fits in.
-![high level architecture overview diagram](../assets/architecture overview.png)
+![high level architecture overview diagram](assets/architecture overview.png)
**NOTE** only use the high-level diagram to get a vague idea, meaning of boxes/arrows may be imprecise.

new_path: docs/assets/architecture overview.png


message: Change diagram to jpg

diff:
@@ -4,7 +4,7 @@ This is a high-level rundown of the architecture of the `OmiseGO` apps.
The below diagram demonstrates the various pieces and where this umbrella app fits in.
-![high level architecture overview diagram](assets/architecture overview.png)
+![high level architecture overview diagram](assets/architecture overview.jpg)
**NOTE** only use the high-level diagram to get a vague idea, meaning of boxes/arrows may be imprecise.

old_path: docs/assets/architecture overview.jpg

new_path: docs/assets/architecture overview.jpg

diff: Binary files /dev/null and b/docs/assets/architecture overview.jpg differ

old_path: docs/assets/architecture overview.png

diff: Binary files a/docs/assets/architecture overview.png and /dev/null differ

original_message: Change diagram to jpg


message: Try again architecture overview diagram

diff:
@@ -4,7 +4,7 @@ This is a high-level rundown of the architecture of the `OmiseGO` apps.
The below diagram demonstrates the various pieces and where this umbrella app fits in.
-![high level architecture overview diagram](assets/architecture overview.jpg)
+![high level architecture overview diagram](assets/architecture_overview.jpg)
**NOTE** only use the high-level diagram to get a vague idea, meaning of boxes/arrows may be imprecise.

original_message: Try again architecture overview diagram


message: Padding around diagram

diff:
This is a high-level rundown of the architecture of the `OmiseGO` apps.
The below diagram demonstrates the various pieces and where this umbrella app fits in.
-
![high level architecture overview diagram](assets/architecture_overview.jpg)
-
**NOTE** only use the high-level diagram to get a vague idea, meaning of boxes/arrows may be imprecise.
## Interactions

original_message: Padding around diagram


message: Solc moved inside bootstrap

diff:
@@ -34,8 +34,6 @@ Set ENVs to compile
source DEV/bin/activate
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
-python3 -m solc.install v0.4.18
-export SOLC_BINARY=/home/vagrant/.py-solc/solc-v0.4.18/bin/solc
```
Get the code and pull elixir dependencies

original_message: Solc moved inside bootstrap


message: Move Vagrant into own repository as per convention

diff:
# 1. Installation via Vagrant
-## Prerequisites
-* Ensure that [Vagrant](https://www.vagrantup.com/) installed on your local machine
-
-Create a directory and the following Vagrantfile:
-```
-Vagrant.configure("2") do |config|
- config.vm.box = "ubuntu/xenial64"
- config.vm.provision "shell", path: "bootstrap.sh"
- config.vm.provider "virtualbox" do |v|https://appear.in/horde-omisego
- v.memory = 4096
- v.cpus = 2
- end
-end
-```
-
-In the same directory, create a bash file named `bootstrap.sh` with the following contents
-https://gist.github.com/Pongch/b38bf178ee9f14dd31cd05fb34e96dce
-
-Run:
-```
-vagrant up --provision
-```
-
-Wait a few minutes for all the dependencies to finish installing
-
-SSH into vagrant:
-```
-vagrant ssh
-```
-
-Set ENVs to compile
-```
-source DEV/bin/activate
-export LC_ALL=C.UTF-8
-export LANG=C.UTF-8
-```
-
-Get the code and pull elixir dependencies
-```
-git clone https://github.com/omisego/omisego
-cd omisego
-HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix deps.get
-
-compile and test
-mix test --no-start
-```
+Refer to https://github.com/omisego/omisego-vagrant.
# 2. Full installation


message: Unnecessary wget of populus/requirements.txt

diff:
@@ -57,14 +57,6 @@ virtualenv DEV
source DEV/bin/activate
```
-## Install populus
-[Ref](../populus/README.md)
-```
-wget https://github.com/omisego/omisego/blob/develop/populus/requirements.txt
-pip3 install -r populus/requirements.txt
-```
-If an error is raised when installing the specific version of `eth-utils`, the error may be ignored for the purposes of this installation.
-
## Install solc
```
sudo apt-get install libssl-dev solc
@@ -74,13 +66,25 @@ sudo apt-get install libssl-dev solc
```
mix do local.hex --force, local.rebar --force
```
-## Clone repo and build
+
+## Clone repo
+```
+git clone https://github.com/omisego/omisego
+```
+
+## Install populus
+[Ref](../populus/README.md)
+```
+pip3 install -r omisego/populus/requirements.txt
+```
+If an error is raised when installing the specific version of `eth-utils`, the error may be ignored for the purposes of this installation.
+
+## Build
```
# populus requires character encoding to be set
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
-git clone https://github.com/omisego/omisego
cd omisego
mix deps.get
```


message: I can't believe I'm so bad at reverting

diff:
@@ -13,151 +13,6 @@ For the responsibilities and design of the watcher see [Tesuji Plasma Blockchain
cd apps/omisego_watcher
mix run --no-halt --config path/to/config.exs
-# OmiseGO Watcher
-
-**IMPORTANT NOTICE: Heavily WIP, expect anything**
-
-The Watcher is an observing node that connects to Ethereum and the child chain server's API.
-It exposes the information it gathers via a REST interface (Phoenix)
-For the responsibilities and design of the watcher see [Tesuji Plasma Blockchain Design document](FIXME link pending).
-
-**TODO** write proper README after we distill how to run this.
-
-## Configure the `omisego_watcher` app
-Create another copy of the configuration file. The values for `contract_addr`, `txhash_contract` and `authority_addr` should be the same as the `omisego_api` app. However, `leveldb_path` should be set to a different directory than `omisego_watcher`.
-
-The configuration file should look something like this:
-
-```
-use Mix.Config
-config :omisego_eth,
- contract_addr: "0x005f49af1af9eee6da214e768683e1cc8ab222ac",
- txhash_contract: "0x3afd2c1b48eaa3100823de1924d42bd48ee25db1fd497998158f903b6a841e92",
- authority_addr: "0x5c1a5e5d94067c51ec51c6c00416da56aac6b9a3"
- leveldb_path: Path.join([System.get_env("HOME"), "~/omisego/data_watcher"])
-
-```
-
-## Setting up and running the watcher
-
-```
-cd apps/omisego_watcher
-# FIXME: wouldn't work yet but would belong here: mix run --no-start -e 'OmiseGO.DB.init()'
-iex --sname watcher -S mix
-```
-
-## Setting up (developer's environment)
-
- - setup and run the child chain server in developer's environment
- - setup and run the watcher pointing to the same `omisego_eth` configuration (with the contract address) as the child chain server
-
-## Using the watcher
-
-FIXME adapt to how it actually works
-
-
-##Endpoints
-TODO
-
-## Websockets
-
-Exposed websockets are using [Phoniex channels](https://hexdocs.pm/phoenix/channels.html) feature.
-Different events are emitted for each topic.
-
-### Topics:
-
-### transfer:ethereum_address
-
-#### Events:
-
-##### address_received and address_spent
-`address_received` event informing about that particular address received funds.
-
-`address_spent` vent informing about that particular address spent funds.
-
-Blocks are validated by the Watcher after a short (not-easily-configurable) finality margin. By consequence, above events will be emitted no earlier than that finality margin.
-In case extra finality is required for high-stakes transactions, the client is free to wait any number of Ethereum blocks (confirmations) on top of submitted_at_ethheight
-
-```json
-{
- "topic": "transfer:0xfd5374cd3fe7ba8626b173a1ca1db68696ff3692",
- "ref": null,
- "payload": {
- "child_blknum": 10000,
- "child_block_hash": "DB32876CC6F26E96B9291682F3AF4A04C2AA2269747839F14F1A8C529CF90225",
- "submited_at_ethheight": 14,
- "tx": {
- "signed_tx": {
- "raw_tx": {
- "amount1": 7,
- "amount2": 3,
- "blknum1": 2001,
- "blknum2": 0,
- "cur12": "0000000000000000000000000000000000000000",
- "newowner1": "051902B7A7D6DCB915CE8FFD3BF46B5E0E16BB9C",
- "newowner2": "E6E3F1307219F68AE4B271CFD493EC8F932C34D9",
- "oindex1": 0,
- "oindex2": 0,
- "txindex1": 0,
- "txindex2": 0
- },
- "sig1": "7B52AB ...",
- "sig2": "2ABGAT ...",
- "signed_tx_bytes": "F8CF83 ..."
- },
- "signed_tx_hash": "0768DC526A093C8C058303832FF3AB45893466D731A34BCF1BF2F866586C0FE6",
- "spender1": "6DCB915C051902B7A7DE8FFD3BF46B5E0E16BB9C",
- "spender2": "5E0E16BB9C19F68AE4B271CFD493EC8F932C34D9"
- }
- },
- "join_ref": null,
- "event": "address_received"
-}
-```
-
-### spends:ethereum_address
-
-#### Events:
-
-##### address_spent
-
-### receives:ethereum_address
-
-#### Events:
-
-##### address_received
-
-### byzantine_invalid_exit
-
-#### Events:
-
-##### in_flight_exit
-
-##### piggyback
-
-##### exit_from_spent
-
-### byzantine_bad_chain
-
-#### Events:
-
-##### invalid_block
-Event informing about that particular block is invalid.
-
-##### block_withholding
-Event informing about that the child chain is withholding block.
-
-##### invalid_fee_exit
-
-### TODO block
-
-### TODO deposit_spendable
-
-### TODO fees
-
-#### Events:
-
-##### fees_exited
## Setting up (developer's environment)

original_message: I can't believe I'm so bad at reverting


message: Assume Elixir 1.6 and rename to elixir-omg

diff:
# 1. Installation via Vagrant
-Refer to https://github.com/omisego/omisego-vagrant.
+Refer to https://github.com/omisego/omg-vagrant.
# 2. Full installation
@@ -33,9 +33,16 @@ sudo apt-get install -y esl-erlang=1:20.3.6
## Install Elixir
```
-sudo apt-get -y install elixir
+sudo apt-get install elixir=1.6.5-1
```
+## Stop Erlang and Elixir from being upgraded
+```
+sudo apt-mark hold esl-erlang
+sudo apt-mark hold elixir
+```
+
+
## Install Geth
```
sudo apt-get install -y software-properties-common
@@ -69,13 +76,13 @@ mix do local.hex --force, local.rebar --force
## Clone repo
```
-git clone https://github.com/omisego/omisego
+git clone https://github.com/omisego/elixir-omg
```
## Install contract building machinery
[Ref](../contracts/README.md)
```
-pip3 install -r omisego/contracts/requirements.txt
+pip3 install -r elixir-omg/contracts/requirements.txt
```
## Build
@@ -84,7 +91,7 @@ pip3 install -r omisego/contracts/requirements.txt
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
-cd omisego
+cd elixir-omg
mix deps.get
```
@@ -100,4 +107,4 @@ mix test --only integration
```
## Next steps
-Follow the README steps for the [child chain server](../apps/omisego_api/README.md).
+Follow the README steps for the [child chain server](../apps/omg_api/README.md).


message: Elixir implementation

diff:
<img src="assets/logo.png" align="right" />
# elixir-omg
-The `elixir-omg` repository contains OmiseGO's implementation of Plasma and forms the basis for the OMG Network.
+The `elixir-omg` repository contains OmiseGO's Elixir implementation of Plasma and forms the basis for the OMG Network.
The first release of the OMG Network is based upon **Tesuji Plasma**, an iterative design step over [Plasma MVP](../plasma-mvp). The diagram below illustrates the relationship between the wallet provider and how wallet providers connect to **Tesuji Plasma**.

original_message: Elixir implementation


message: Rename omisego_ to omg_

diff:
# Architecture
-This is a high-level rundown of the architecture of the `OmiseGO` apps.
+This is a high-level rundown of the architecture of the `elixir-omg` apps.
The below diagram demonstrates the various pieces and where this umbrella app fits in.
![high level architecture overview diagram](assets/architecture_overview.jpg)
@@ -14,12 +14,12 @@ This lists only interactions between the different processes that build up both
For responsibilities of the processes/modules look into respective docs in `.ex` files.
**NOTE**:
-- for `OmiseGO.API` modules/processes look in `apps/omisego_api`
-- for `OmiseGOWatcher` modules/processes look in `apps/omisego_watcher`
-- for `OmiseGO.Eth` look in `apps/omisego_eth`
-- for `OmiseGO.DB` look in `apps/omisego_db`
-- for `OmiseGO.Performance` look in `apps/omisego_performance`
-- for `OmiseGO.JSONRPC` look in `apps/omisego_jsonrpc`
+- for `OmiseGO.API` modules/processes look in `apps/omg_api`
+- for `OmiseGOWatcher` modules/processes look in `apps/omg_watcher`
+- for `OmiseGO.Eth` look in `apps/omg_eth`
+- for `OmiseGO.DB` look in `apps/omg_db`
+- for `OmiseGO.Performance` look in `apps/omg_performance`
+- for `OmiseGO.JSONRPC` look in `apps/omg_jsonrpc`
**NOTE 2** The hexagonal shape hints towards component being a wrapper (port/adapter) to something external, versus rectangular shape being an internal component.

diff:
# Troubleshooting
-## Configuring the omisego_eth app fails with error
+## Configuring the omg_eth app fails with error
```
** (MatchError) no match of right hand side value: {:error, :econnrefused}
lib/eth/dev_helpers.ex:44: OmiseGO.Eth.DevHelpers.create_and_fund_authority_addr/0

original_message: Rename omisego_ to omg_


message: ENVS need to be set before pip install

diff:
@@ -82,15 +82,14 @@ git clone https://github.com/omisego/elixir-omg
## Install contract building machinery
[Ref](../contracts/README.md)
```
+# contract building requires character encoding to be set
+export LC_ALL=C.UTF-8
+export LANG=C.UTF-8
pip3 install -r elixir-omg/contracts/requirements.txt
```
## Build
```
-# contract building requires character encoding to be set
-export LC_ALL=C.UTF-8
-export LANG=C.UTF-8
-
cd elixir-omg
mix deps.get
```

original_message: ENVS need to be set before pip install


message: Restricted Limited Custody -> Restricted Custody

diff:
@@ -330,7 +330,7 @@ These value propositions still need to be validated for each of the target users
Existing crypto exchanges can be hacked, leading to loss of user funds, loss of capital and loss of user confidence in the crypto ecosystem. Traditional venues (typically regulated) would like to participate in the crypto markets and offer services to their users but face all the same issues as crypto venues and therefore expose themselves to significant reputational damage and fail to offer a secure enough market to be attractive to their existing members. Both venue types could benefit significantly from:
-* Restricted Limited Custody of user funds
+* Restricted custody of user funds
* Reduced regulatory exposure (such as not taking user deposits)


message: Add full list of API endpoints and events

diff:
@@ -84,22 +84,70 @@ RESPONSE 500
}
}
```
-## OmiseGo Plasma API
-An incomplete list of endpoints to demonstrate the format:
+## OmiseGO Plasma API
+There are three services involved
+
+### 1. ChildChain
+Normally a user wouldn't call the ChildChain API directly, as doing so would lose the security features of the Watcher. However there may be some low-stake accounts that don't care or are fine with some amount of trust in the ChildChain operator. These users can call e.g. `submit` on the ChildChain directly.
+
+#### API endpoints
+```
+/block.get
+/transaction.submit
+```
+
+### 2. Watcher
+The watcher first and foremost plays a critical security role in the system. The watcher monitors the child chain and root chain (Ethereum) for faulty activity.
+
+#### API endpoints
+```
+/transaction.get
+/transaction.submit
+/utxo.get_exit_data
+/utxo.get_challenge_data
+/status
+```
+
+#### Events
+```
+ new_block
+ new_transaction
+ new_deposit
+ exit_started
+ exit_challenged
+ inflight_exit_started
+ inflight_exit_challenged
+ exit_success
+ piggyback
+ invalid_block
+ unchallenged_exit
+ block_withholding
+ invalid_fee_exit
+```
+
+
+### 3. Informational/Convenience API
+This service may end up being included in the Watcher as optional functionality, but conceptually it can be seen as a separate service. It stores informational data about the chain, and provides convenience APIs to proxy to the child chain/root chain/watcher to ease integration and reduce duplicate code in libraries.
+
+#### API endpoints
```
/account.get_balance
/account.get_utxos
/account.get_transactions
-/utxo.get_exit_data
-/utxo.get_challenge_data
+/transaction.all
/transaction.get
/transaction.create
-/transaction.submit
+/block.all
/block.get
-/status
+... utxo management apis ...
```
-## Architecture
-Suggestion from Robin is to have a sort of ReverseProxy app that sits in front of the other services and routes the calls to the appropriate service e.g. `/api/transaction.submit` goes to the ChildChain and `/api/account.get_utxos` goes to the Watcher.
+#### Events
+```
+ transaction_confirmed
+ address_received
+ address_spent
+```
-I think this can work with HTTP calls, although I'm not sure about WebSockets...
+## Architecture
+To be decided...
\ No newline at end of file


message: Changes following PR comments

diff:
API specification of the Watcher's security-critical Service
+## Account - Get Utxos
+
+```shell
+http POST /account.get_utxos address=b3256026863eb6ae5b06fa396ab09069784ea8ea
+```
+
+```elixir
+// TODO
+```
+
+```javascript
+// TODO
+```
+
+> The above command returns JSON document:
+
+```json
+{
+ "version": "1",
+ "success": true,
+ "data": [
+ {
+ "txindex": 1,
+ "owner": "B3256026863EB6AE5B06FA396AB09069784EA8EA",
+ "oindex": 0,
+ "currency": "0000000000000000000000000000000000000000",
+ "blknum": 1000,
+ "amount": 10
+ }
+ ]
+}
+```
+
+Gets all utxos belonging to the given address.
+<aside class="warning"> Note that this is a performance intensive call and should only be used if the chain is byzantine and the user needs to retrieve utxo information to be able to exit. Normally an application should use the Informational API `/account.get_utxos`. This version is provided in case the Informational API is not available.</aside>
+
+
+### HTTP Request
+
+`POST /account.get_utxos`
+
+### JSON Body
+
+Key | Type | Description
+--------- | ------- | -----------
+address | Hex encoded string | Address of the account
+limit | Integer | Maximum number of utxos to return (optional)
+
+
## Utxo - Get Challenge Data

diff:
-# Watcher - Websocket API
+# Watcher - Events
+The most critical function of the Watcher is to monitor the ChildChain and report any dishonest activity.
+
+TODO Explanation of the WebSocket/ Phoenix Channels mechanism used to receive events
+
+## Topic `byzantine`
+All of the following events indicate a byzantine chain and that the user should either exit or challenge.
+
+### Event `block_withholding`
+
+Event informing that child chain is withholding block which hash was published on root chain.
+
+> Event type have following structure.
+
+Key | Type | Description
+--------- | ------- | -----------
+blknum | Integer | Number of plasma block
+
+
+### Event `invalid_block`
+
+Event informing that a particular block is invalid.
+
+> Event type have following structure.
+
+Key | Type | Description
+--------- | ------- | -----------
+hash | HEX-encoded string | Hash of plasma block
+number | Integer | Number of plasma block
+error_type | String |
+
+
+### Event `invalid_exit`
+
+Event informing that invalid exit has started
+
+> Event type have following structure.
+
+Key | Type | Description
+--------- | ------- | -----------
+amount | Integer |
+currency | HEX-encoded string |
+owner | HEX-encoded string |
+utxo_pos | Integer |
+eth_height | Integer |
+
+
+### Event `unchallenged_exit`
+
+Notifies about an invalid exit, that is dangerously approaching finalization, without being challenged.
+It is a prompt to exit.
+
+> Event type have following structure.
+
+Key | Type | Description
+--------- | ------- | -----------
+amount | Integer |
+currency | HEX-encoded string |
+owner | HEX-encoded string |
+utxo_pos | Integer |
+eth_height | Integer |
+
+
+### Event `invalid_in_flight_exit`
+
+Event informing of an invalid in-flight exit, a kmown competitor should be provided.
+
+> Event type have following structure.
+
+Key | Type | Description
+--------- | ------- | -----------
+amount | Integer |
+currency | HEX-encoded string |
+owner | HEX-encoded string |
+utxo_pos | Integer |
+eth_height | Integer |
+
+
+### Event `invalid_in_flight_challenge`
+
+Event informing of an invalid in-flight challenge, proof of canonicity should be provided.
+
+> Event type have following structure.
+
+Key | Type | Description
+--------- | ------- | -----------
+amount | Integer |
+currency | HEX-encoded string |
+owner | HEX-encoded string |
+utxo_pos | Integer |
+eth_height | Integer |
+
+
+### Event `piggyback_required`
+
+Event informing that a piggyback on an in-flight exit is required
+
+> Event type have following structure.
+
+Key | Type | Description
+--------- | ------- | -----------
+amount | Integer |
+currency | HEX-encoded string |
+owner | HEX-encoded string |
+utxo_pos | Integer |
+eth_height | Integer |
+
+
+### Event `invalid_piggyback`
+
+Event informing of an invalid piggyback. It should be challenged.
+
+> Event type have following structure.
+
+Key | Type | Description
+--------- | ------- | -----------
+amount | Integer |
+currency | HEX-encoded string |
+owner | HEX-encoded string |
+utxo_pos | Integer |
+eth_height | Integer |
+
+
## Topic `transfer:{address}`
@@ -60,80 +182,33 @@ Blocks are validated by the Watcher after a short (not-easily-configurable) fina
}
```
-## Topic `byzantine`
-### Event `block_withholding`
+## Topic `childchain`
-Event informing that child chain is withholding block which hash was published on root chain.
+### Events `new_block`
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-blknum | Integer | Number of plasma block
-
-
-### Event `invalid_block`
-
-Event informing that a particular block is invalid.
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-hash | HEX-encoded string | Hash of plasma block
-number | Integer | Number of plasma block
-error_type | String |
-
-
-### Event `invalid_exit`
-
-Event informing that invalid exit has started
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-amount | Integer |
-currency | HEX-encoded string |
-owner | HEX-encoded string |
-utxo_pos | Integer |
-eth_height | Integer |
-
-
-### Event `unchallenged_exit`
-
-Notifies about an invalid exit, that is dangerously approaching finalization, without being challneged.
-It is a prompt to exit.
-
-> Event type have following structure.
+Informs that a new block has been added to the chain.
+> Both event types have the same structure.
Key | Type | Description
--------- | ------- | -----------
-amount | Integer |
-currency | HEX-encoded string |
-owner | HEX-encoded string |
-utxo_pos | Integer |
-eth_height | Integer |
-
+blknum | Integer |
+block_hash | HEX-encoded string |
+ethheight | integer |
+timestamp | integer |
-## Other planned events
-in no particular order or severity
-To be clarified...
+# RootChain - Events
+The RootChain contract raises certain events on Ethereum
+TODO We may want to forward these events through the watcher
+TODO Most of these events are not currently implemented in the RootChain contract
+ * new_deposit
+ * exit_started
+ * exit_challenged
+ * exit_finalized
* inflight_exit_started
* inflight_exit_challenged
* piggyback_to_input
* piggyback_to_output
- * invalid_fee_exit
* fees_exited
- * fees
- * new_block
- * new_transaction
- * new_deposit
- * deposit_spendable
- * exit_started
- * exit_challenged
- * exit_success
-

original_message: Changes following PR comments


message: Move api markdown files

diff:
@@ -10,6 +10,11 @@ toc_footers:
- Documentation Powered by Slate
includes:
+ - operator_api_specs
+ - watcher_api_specs
+ - watcher_websocket_specs
+ - informational_api_specs
+ - integration_libraries
search: true
---

original_message: Move api markdown files


message: Add errors.md

diff:
+# Errors
+
+Note that HTTP calls will almost always return `200`, even if the result is an error. One exception to this is if an internal server error occurs - in this case it will return `500`
+
+When an error occurs, `success` will be set to `false` and `data` will contain more information about the error
+
+```json
+{
+ "version": "1",
+ "success": false,
+ "data": {
+ "code": "account:not_found",
+ "description": "Account not found"
+ }
+}
+```
\ No newline at end of file

diff:
@@ -15,6 +15,7 @@ includes:
- watcher_websocket_specs
- informational_api_specs
- integration_libraries
+ - errors
search: true
---

original_message: Add errors.md


message: Byzantine events returned from `status` endpoint

diff:
@@ -207,7 +207,20 @@ http POST /status
"last_validated_child_block_number": 10000,
"last_mined_child_block_timestamp": 1535031020,
"last_mined_child_block_number": 11000,
- "eth_syncing": true
+ "eth_syncing": true,
+ "byzantine_events":
+ [
+ {
+ "event": "invalid_exit",
+ "details": {
+ "eth_height" : 100,
+ "utxo_pos" : 100,
+ "owner" : "B3256026863EB6AE5B06FA396AB09069784EA8EA",
+ "currency" : "0000000000000000000000000000000000000000",
+ "amount" : 100
+ }
+ }
+ ]
}
}
```
@@ -222,4 +235,77 @@ Gets plasma network and Watcher status
No parameters are required.
+<aside class="warning">
+The most critical function of the Watcher is to monitor the ChildChain and report dishonest activity.
+The user must call the `/status` endpoint periodically to check. Any situation that requires the user to either exit or challenge an invalid exit will be included in the `byzantine_events` field.
+</aside>
+
+### Byzantine events
+All of the following events indicate a byzantine chain and that the user should either exit or challenge.
+
+#### `invalid_exit`
+
+Indicates that an invalid exit is occurring. It should be challenged.
+
+> invalid_exit
+```json
+{
+ "event": "invalid_exit",
+ "details": {
+ "eth_height" : 3521678,
+ "utxo_pos" : 12,
+ "owner" : "B3256026863EB6AE5B06FA396AB09069784EA8EA",
+ "currency" : "0000000000000000000000000000000000000000",
+ "amount" : 100
+ }
+}
+```
+
+
+#### `unchallenged_exit`
+
+Indicates that an invalid exit is dangerously close to finalization and hasn't been challenged. User should exit.
+> unchallenged_exit
+```json
+{
+ "event": "invalid_exit",
+ "details": {
+ "eth_height" : 3521678,
+ "utxo_pos" : 12,
+ "owner" : "B3256026863EB6AE5B06FA396AB09069784EA8EA",
+ "currency" : "0000000000000000000000000000000000000000",
+ "amount" : 100
+ }
+}
+```
+
+#### `invalid_block`
+
+A block containing an invalid tx has been processed [are there other reasons a block can be invalid?]. User should exit.
+
+> invalid_block
+```json
+{
+ "event": "invalid_exit",
+ "details": {
+ "blockhash" : "DB32876CC6F26E96B9291682F3AF4A04C2AA2269747839F14F1A8C529CF90225",
+ "blocknum" : 10000,
+ }
+}
+```
+
+#### `block_withholding`
+
+The ChildChain is withholding a block whose hash has been published on the root chain. User should exit.
+
+> block_withholding
+```json
+{
+ "event": "invalid_exit",
+ "details": {
+ "blockhash" : "DB32876CC6F26E96B9291682F3AF4A04C2AA2269747839F14F1A8C529CF90225",
+ "blocknum" : 10000,
+ }
+}
+```

diff:
# Watcher - Events
-The most critical function of the Watcher is to monitor the ChildChain and report any dishonest activity.
<aside class="warning">TODO Explanation of the WebSocket/ Phoenix Channels mechanism used to receive events</aside>
-## Topic `byzantine`
-All of the following events indicate a byzantine chain and that the user should either exit or challenge.
-
-### Event `block_withholding`
-
-Event informing that child chain is withholding block which hash was published on root chain.
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-blknum | Integer | Number of plasma block
-
-
-### Event `invalid_block`
-
-Event informing that a particular block is invalid.
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-hash | HEX-encoded string | Hash of plasma block
-number | Integer | Number of plasma block
-error_type | String |
-
-
-### Event `invalid_exit`
-
-Event informing that invalid exit has started
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-amount | Integer |
-currency | HEX-encoded string |
-owner | HEX-encoded string |
-utxo_pos | Integer |
-eth_height | Integer |
-
-
-### Event `unchallenged_exit`
-
-Notifies about an invalid exit, that is dangerously approaching finalization, without being challenged.
-It is a prompt to exit.
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-amount | Integer |
-currency | HEX-encoded string |
-owner | HEX-encoded string |
-utxo_pos | Integer |
-eth_height | Integer |
-
-
-### Event `invalid_in_flight_exit`
-
-Event informing of an invalid in-flight exit, a kmown competitor should be provided.
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-amount | Integer |
-currency | HEX-encoded string |
-owner | HEX-encoded string |
-utxo_pos | Integer |
-eth_height | Integer |
-
-
-### Event `invalid_in_flight_challenge`
-
-Event informing of an invalid in-flight challenge, proof of canonicity should be provided.
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-amount | Integer |
-currency | HEX-encoded string |
-owner | HEX-encoded string |
-utxo_pos | Integer |
-eth_height | Integer |
-
-
-### Event `piggyback_required`
-
-Event informing that a piggyback on an in-flight exit is required
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-amount | Integer |
-currency | HEX-encoded string |
-owner | HEX-encoded string |
-utxo_pos | Integer |
-eth_height | Integer |
-
-
-### Event `invalid_piggyback`
-
-Event informing of an invalid piggyback. It should be challenged.
-
-> Event type have following structure.
-
-Key | Type | Description
---------- | ------- | -----------
-amount | Integer |
-currency | HEX-encoded string |
-owner | HEX-encoded string |
-utxo_pos | Integer |
-eth_height | Integer |
-
-
-
## Topic `transfer:{address}`
### Events `address_received` and `address_spent`


message:
Update exit_validation.md
Fix some typos and change wording to (I think) clarify some points.

diff:
@@ -14,52 +14,52 @@ This document focuses on the Watcher.
For completeness we give a quick run-down of the rules followed by the Child Chain Server, in terms of processing exits sent on the root chain contract.
-1. Child Chain operator's objective is to pro-actively minimize the risk of chain becoming invalid.
-The risk is that this can happen if any exit gets finalized despite being invalid.
+1. The Child Chain operator's objective is to pro-actively minimize the risk of chain becoming invalid.
+The Child Chain will become invalid if any invalid exit gets finalized.
2. To satisfy this objective:
- - the child chain server listens to every `ExitStarted` event and immediately "spends" the exited utxo, preventing exit invalidation
- - the child chain server listens to every `InFlightExitStarted` event and immediately "spends" the exiting tx's **inputs**
- - the child chain server listens to every `InFlightExitPiggybacked` event (on outputs) and immediately "spends" the piggybacked outputs - as long as the IFEing tx has been included in the chain and the output exists
+ - the Child Chain server listens to every `ExitStarted` Root Chain event and immediately "spends" the exited utxo. This blocks the user from spending that utxo, thus preventing exit invalidation.
+ - the Child Chain server listens to every `InFlightExitStarted` Root Chain event and immediately "spends" the exiting tx's **inputs**
+ - the Child Chain server listens to every `InFlightExitPiggybacked` Root Chain event (on outputs) and immediately "spends" the piggybacked outputs - as long as the IFEing tx has been included in the chain and the output exists
There are scenarios, when a race condition/reorg on the root chain might make the Child Chain Server block spending of a particular UTXO **too late**, regardless of the immediacy mentioned above.
-This is OK, as long as the delay doesn't exceed a predetermined `sla_margin`.
+This is acceptable as long as the delay doesn't exceed a predetermined `sla_margin`.
## Standard Exits
### The purpose of having exit validation as a separate service is to:
-1. proactively prevent user from losing money
- - prohibit user from spending on a dangerous chain
- - try to preempt underfunded chain situation, which would jeopardize user's funds
-2. letting know user about byzantine child chain as reasonably fast as possible
-4. (optional) protect against loss in case of invalid exit finalization
-5. prevent spurious prompts to mass exit, that might result from root chain reorgs, race conditions etc.
+1. proactively prevent the user from losing money by:
+ - prohibiting the user from spending on a dangerous chain
+ - trying to preempt underfunded chain situation, which would jeopardize user's funds
+2. let the user know about byzantine child chain as soon as is reasonably possible
+4. (optional) protect against loss in case of an invalid exit finalization
+5. prevent spurious prompts to mass exit that might result from root chain reorgs, race conditions etc.
### Actions that the Watcher should prompt:
1. If an exit is known to be invalid it should be challenged (almost) immediately
2. If an exit is invalidated with a transaction submitted within an acceptable `sla_margin` period it must be challenged
3. If an exit is invalidated with a transaction submitted after an acceptable `sla_margin` period it must be challenged **AND** watcher must prompt an exit **AND** watcher must not allow spending and depositing
- - because our child chain implementation will never get close to this happening, so it is a symptom of a (subtle) hack of the child chain server.
+ - because our child chain implementation will never get close to this happening, so it is a symptom of a (subtle) hack attempt on the child chain server.
By "subtle" we mean that it is a hack that counts on getting away with exit invalidation being submitted too late, rather than on just dropping a huge invalid UTXO and attempting to exit from that
-3. If an exit is invalid and unchallenged within a short period from it's finalization it must be challenged **AND** watcher must not allow spending and depositing
- - because otherwise, we are "tightly" following the minimum safety requirements
- - because otherwise, unchallenged exits may break the chain without honest holders having time to escape.
- This is the case when an exit, a spend invalidating it and exit of that coincide and are unchallenged.
-4. (optional) If a finalization of an invalid exit occurs, watcher must prompt an exit without guarantees of recovery of funds
+3. If an exit is invalid and remains unchallenged within a short period of time from its finalization, it must be challenged **AND** watcher must not allow spending and depositing, because:
+ a. we are running too close to the minimum safety requirements
+ b. unchallenged exits may break the chain without leaving honest holders with enough time to exit.
+ This can happen when an exit, a spend that invalidates that exit and an exit of that invalidating spend all coincide and are unchallenged.
+4. (optional) If finalization of an invalid exit occurs, the watcher must prompt an exit without guarantees of recovery of funds
Conditions 3 and 4 can be represented jointly, by **continuous** (every child block) validation of the exits.
-If any exit is invalid and its finalization is near, then actions listed under 3 and 4 should take place
+If any exit is invalid and its finalization is near, then actions listed under 3 and 4 should take place.
All that takes as an assumption that:
- - the user's funds must be safe even if the user syncs and validates the chain periodically (but not less frequently than required)
- - user needs to have the ability to constantly spend their UTXOs, thereby requiring more stringent validity checking of exits
+ - the user's funds must be safe even if the user only syncs and validates the chain periodically (but not less frequently than required)
+ - the user needs to have the ability to spend their UTXOs at any time, thereby requiring more stringent validity checking of exits
### Example cases for above actions:
-1. The exit is processed after the tx, so it is known to be invalid from the start. Should emit an `:invalid_exit` event.
-2. The exit is processed before the tx, but the tx is within `sla_margin` period, so the child chain is valid.
+1. The exit is processed *after* the tx that invalidates it, so it is known to be invalid from the start. Should emit an `:invalid_exit` event.
+2. The exit is processed *before* the tx that invalidates it and the tx is within `sla_margin` period, so the child chain is still valid.
Causes an `:invalid_exit` event.
-3. The exit is processed before the tx, but tx is after `sla_margin` period, so the child chain is byzantine.
+3. The exit is processed *before* the tx that invalidates it, but the tx occurs *after* `sla_margin` period, so the child chain is byzantine.
Causes to emit an `:unchallenged_exit` event.
-3. An exit is unchallenged within `sla_margin` period, so the child chain is jeopardized.
+3. An invalid exit is still unchallenged after `sla_margin` period, so the child chain is jeopardized.
Causes to emit an `:unchallenged_exit` event.
4. (optional) Continuation of cases (1) or (2) where the exit never gets challenged and finalizes.
Causes to emit an `:invalid_finalization` event