├── .circleci └── config.yml ├── .codacy.yml ├── .codeclimate.yml ├── .codecov.yml ├── .dockerignore ├── .gitignore ├── .golangci.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── Dockerfile.dev ├── Dockerfile.tools ├── LICENSE ├── Makefile ├── README.md ├── app ├── app.go └── export.go ├── cmd ├── mesg-cli │ ├── main.go │ ├── orchestrator.go │ ├── serve.go │ └── sign.go └── mesg-daemon │ ├── genaccounts.go │ └── main.go ├── container └── container.go ├── cosmos ├── config.go ├── keybase.go ├── keybase_test.go ├── lcd.go ├── rpc.go └── simulate.go ├── dev-chain ├── README.md ├── cli │ └── config │ │ └── config.toml └── validator │ ├── config │ ├── app.toml │ ├── config.toml │ ├── genesis.json │ ├── node_key.json │ └── priv_validator_key.json │ └── data │ └── priv_validator_state.json ├── e2e ├── account_sequence_test.go ├── api_test.go ├── complex_service_test.go ├── credit_test.go ├── definition_test.go ├── event_test.go ├── execution_test.go ├── instance_test.go ├── orchestrator_balance_withdraw_test.go ├── orchestrator_event_task_test.go ├── orchestrator_filter_path_nested_test.go ├── orchestrator_filter_test.go ├── orchestrator_map_const_test.go ├── orchestrator_nested_data_test.go ├── orchestrator_nested_map_test.go ├── orchestrator_ref_grand_parent_task_test.go ├── orchestrator_ref_path_nested_test.go ├── orchestrator_result_task_test.go ├── orchestrator_test.go ├── process_test.go ├── runner_test.go ├── service_test.go └── testdata │ ├── test-complex-service │ ├── Dockerfile │ ├── go.mod │ ├── go.sum │ └── main.go │ └── test-service │ ├── Dockerfile │ ├── go.mod │ ├── go.sum │ └── main.go ├── event ├── event.go ├── event.pb.go ├── event_listener.go ├── event_listener_test.go └── publisher │ └── publisher.go ├── execution ├── error.go ├── execution.go ├── execution.pb.go ├── execution_test.go └── sort.go ├── ext ├── xerrors │ ├── errors.go │ └── errors_test.go ├── xnet │ ├── dnsclient.go │ ├── ip_test.go │ └── ipsock.go ├── xos │ ├── env.go │ └── env_test.go ├── xrand │ └── seed.go ├── xreflect │ ├── xreflect.go │ └── xreflect_test.go ├── xsignal │ ├── signal.go │ └── signal_test.go ├── xstrings │ ├── strings.go │ └── strings_test.go └── xvalidator │ └── validator.go ├── go.mod ├── go.sum ├── hash ├── hash.go ├── hash_test.go └── structhash │ ├── structhash.go │ └── structhash_test.go ├── instance ├── instance.go └── instance.pb.go ├── internal └── tools │ └── tools.go ├── orchestrator ├── orchestrator.go └── orchestrator_test.go ├── ownership ├── ownership.go └── ownership.pb.go ├── process ├── codec.go ├── filter.go ├── filter_test.go ├── graph.go ├── graph_test.go ├── node.go ├── process.go ├── process.pb.go ├── process_test.go └── ref.go ├── protobuf ├── acknowledgement │ └── stream.go └── types │ ├── codec.go │ ├── event.proto │ ├── execution.proto │ ├── instance.proto │ ├── ownership.proto │ ├── process.proto │ ├── runner.proto │ ├── service.proto │ ├── struct.go │ ├── struct.pb.go │ ├── struct.proto │ └── struct_test.go ├── runner ├── runner.go └── runner.pb.go ├── schema1.svg ├── scripts ├── build-proto.sh ├── changelog.sh ├── dev-starter.sh ├── dev.sh ├── monitoring │ ├── dashboard.yml │ ├── dashboards │ │ ├── cosmos.json │ │ └── execution.json │ ├── datasource.yml │ └── prometheus.yml └── run-e2e.sh ├── server └── grpc │ ├── logger.go │ ├── orchestrator │ ├── authorizer.go │ ├── event.go │ ├── event.pb.go │ ├── event.proto │ ├── execution.go │ ├── execution.pb.go │ ├── execution.proto │ ├── runner.go │ ├── runner.pb.go │ └── runner.proto │ ├── runner │ ├── runner.go │ ├── runner.pb.go │ └── runner.proto │ └── server.go ├── service ├── service.go ├── service.pb.go ├── service_parameter.go ├── service_parameter_test.go ├── service_test.go └── validate.go └── x ├── credit ├── abci.go ├── alias.go ├── client │ ├── cli │ │ ├── query.go │ │ └── tx.go │ └── rest │ │ ├── query.go │ │ ├── rest.go │ │ └── tx.go ├── genesis.go ├── handler.go ├── internal │ ├── keeper │ │ ├── keeper.go │ │ ├── params.go │ │ └── querier.go │ └── types │ │ ├── codec.go │ │ ├── events.go │ │ ├── expected_keepers.go │ │ ├── genesis.go │ │ ├── key.go │ │ ├── msg.go │ │ ├── msg.pb.go │ │ ├── msg.proto │ │ ├── params.go │ │ └── querier.go └── module.go ├── execution ├── abci.go ├── alias.go ├── client │ ├── cli │ │ ├── query.go │ │ └── tx.go │ └── rest │ │ ├── query.go │ │ ├── rest.go │ │ └── tx.go ├── genesis.go ├── handler.go ├── internal │ ├── keeper │ │ ├── keeper.go │ │ ├── metrics.go │ │ └── querier.go │ └── types │ │ ├── codec.go │ │ ├── events.go │ │ ├── expected_keepers.go │ │ ├── genesis.go │ │ ├── key.go │ │ ├── msg.go │ │ ├── msg.pb.go │ │ ├── msg.proto │ │ └── querier.go └── module.go ├── instance ├── abci.go ├── alias.go ├── client │ ├── cli │ │ ├── query.go │ │ └── tx.go │ └── rest │ │ ├── query.go │ │ ├── rest.go │ │ └── tx.go ├── genesis.go ├── handler.go ├── internal │ ├── keeper │ │ ├── keeper.go │ │ └── querier.go │ └── types │ │ ├── codec.go │ │ ├── events.go │ │ ├── expected_keepers.go │ │ ├── genesis.go │ │ ├── key.go │ │ └── querier.go └── module.go ├── ownership ├── abci.go ├── alias.go ├── client │ ├── cli │ │ ├── query.go │ │ └── tx.go │ └── rest │ │ ├── query.go │ │ ├── rest.go │ │ └── tx.go ├── genesis.go ├── handler.go ├── internal │ ├── keeper │ │ ├── keeper.go │ │ └── querier.go │ └── types │ │ ├── codec.go │ │ ├── events.go │ │ ├── expected_keepers.go │ │ ├── genesis.go │ │ ├── key.go │ │ ├── msg.go │ │ ├── msg.pb.go │ │ ├── msg.proto │ │ └── querier.go └── module.go ├── process ├── abci.go ├── alias.go ├── client │ ├── cli │ │ ├── query.go │ │ └── tx.go │ └── rest │ │ ├── query.go │ │ ├── rest.go │ │ └── tx.go ├── genesis.go ├── handler.go ├── internal │ ├── keeper │ │ ├── keeper.go │ │ └── querier.go │ └── types │ │ ├── codec.go │ │ ├── events.go │ │ ├── expected_keepers.go │ │ ├── genesis.go │ │ ├── key.go │ │ ├── msg.go │ │ ├── msg.pb.go │ │ ├── msg.proto │ │ └── querier.go └── module.go ├── runner ├── abci.go ├── alias.go ├── client │ ├── cli │ │ ├── query.go │ │ └── tx.go │ └── rest │ │ ├── query.go │ │ ├── rest.go │ │ └── tx.go ├── genesis.go ├── handler.go ├── internal │ ├── keeper │ │ ├── keeper.go │ │ └── querier.go │ └── types │ │ ├── codec.go │ │ ├── events.go │ │ ├── expected_keepers.go │ │ ├── genesis.go │ │ ├── key.go │ │ ├── msg.go │ │ ├── msg.pb.go │ │ ├── msg.proto │ │ └── querier.go └── module.go └── service ├── abci.go ├── alias.go ├── client ├── cli │ ├── query.go │ └── tx.go └── rest │ ├── query.go │ ├── rest.go │ └── tx.go ├── genesis.go ├── handler.go ├── internal ├── keeper │ ├── keeper.go │ └── querier.go └── types │ ├── codec.go │ ├── events.go │ ├── expected_keepers.go │ ├── genesis.go │ ├── key.go │ ├── msg.go │ ├── msg.pb.go │ ├── msg.proto │ └── querier.go └── module.go /.codacy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | exclude_paths: 3 | - "**/*_test.go" 4 | - "**/*.d.ts" 5 | - "**/*.pb.go" 6 | - "**/Dockerfile" 7 | - "service/importer/assets/*.go" 8 | - "cmd/service/assets/*.go" 9 | - "cmd/service/tests/**/*" 10 | - "service-test/**" 11 | - "docs/**" 12 | - "**/vendor/**/*" 13 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | exclude_patterns: 2 | - "**/*_test.go" 3 | - "**/*.d.ts" 4 | - "**/*.pb.go" 5 | - "service/importer/assets/*.go" 6 | - "commands/provider/assets/" 7 | - "cmd/service/assets/*.go" 8 | - "cmd/service/tests/**/*" 9 | - "service-test/**" 10 | - "docs/**/*" 11 | - "**/vendor/" 12 | - "**/mocks/*" 13 | plugins: 14 | gofmt: 15 | enabled: true 16 | golint: 17 | enabled: true 18 | govet: 19 | enabled: true 20 | 21 | checks: 22 | return-statements: 23 | config: 24 | threshold: 6 25 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | comment: off 2 | ignore: 3 | - "**/*.pb.go" # ignore all protobuff generated files 4 | - "**/*.md" # ignore all markdown files 5 | - "**/*.yml" # ignore all yml files 6 | - "Dockerfile" 7 | - ".dockerignore" 8 | - ".circleci/config.yml" 9 | - "service/importer/assets/*.go" 10 | - "cmd/service/assets/*.go" 11 | - "cmd/service/tests" 12 | - "docs/**/*" 13 | - "**/vendor/" 14 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | 3 | # build 4 | /bin 5 | 6 | # repo files 7 | README.md 8 | CHANGELOG.md 9 | CONTRIBUTING.md 10 | schema1.svg 11 | .github 12 | 13 | /examples 14 | 15 | # test & debug files 16 | **/*_test.go 17 | **/*.test 18 | **/debug 19 | **/node_modules 20 | /test 21 | /vendor 22 | coverage.txt 23 | 24 | # configuration & repo files 25 | .circleci 26 | .codacy.yml 27 | .codeclimate.yml 28 | .codecov.yml 29 | .git 30 | .gitignore 31 | .golangci.yml 32 | .genesis 33 | .vscode 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | coverage.txt 14 | 15 | .vscode 16 | debug 17 | .DS_Store 18 | 19 | /bin 20 | /test 21 | node_modules 22 | 23 | # do not store vendor dir 24 | vendor 25 | tmp-systemservices 26 | 27 | # genesis 28 | .genesis 29 | 30 | # gogo extension 31 | gogo/ 32 | 33 | main 34 | engine 35 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | tests: true 3 | skip-files: 4 | - ".*.pb.go$" 5 | 6 | linters-settings: 7 | govet: 8 | check-shadowing: false 9 | golint: 10 | min-confidence: 0 11 | gocyclo: 12 | min-complexity: 20 13 | maligned: 14 | suggest-new: true 15 | misspell: 16 | locale: US 17 | 18 | linters: 19 | disable-all: true 20 | enable: 21 | - bodyclose 22 | - deadcode 23 | - dogsled 24 | - gocritic 25 | - gocyclo 26 | - gofmt 27 | - goimports 28 | - golint 29 | - gosimple 30 | - govet 31 | - ineffassign 32 | - maligned 33 | - misspell 34 | - nakedret 35 | - scopelint 36 | - staticcheck 37 | - structcheck 38 | - typecheck 39 | - unconvert 40 | - unparam 41 | - unused 42 | - varcheck 43 | - whitespace 44 | - depguard 45 | - goconst 46 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Issues 2 | 3 | For issues concerning application or service development, please read the [docs](https://docs.mesg.com/) and check out the [forum](https://forum.mesg.com) 4 | 5 | For questions or suggestions regarding new features of Engine, please post a message on the [Forum](https://forum.mesg.com). 6 | 7 | To report a bug, please [check for existing issues, then if you can't find your issue, create a new one on this repository](https://github.com/mesg-foundation/engine/issues). 8 | 9 | # Contribution 10 | 11 | For contributions to Services and Applications, we have a [curated list of Awesome Services and Applications](https://github.com/mesg-foundation/awesome) that we'd love for you to participate in. 12 | 13 | For contribution to MESG Engine, be sure to subscribe to the development/engine category on the [forum](https://forum.mesg.com/c/development/engine) and reach out to us. We would love to include you in the development process. 14 | 15 | # Start Developing Engine 16 | 17 | You can find all resources on our [wiki](https://github.com/mesg-foundation/engine/wiki). It will guide you through creating a pull request, to building and testing it, then submitting your work to the community. 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG from=golang:1.13.10 2 | FROM $from AS build 3 | WORKDIR /app 4 | 5 | COPY go.mod go.sum ./ 6 | RUN go mod download 7 | 8 | COPY . . 9 | ARG version 10 | 11 | RUN make build 12 | 13 | # ubuntu image with binaries for distribution 14 | FROM ubuntu:18.04 15 | RUN apt-get update && \ 16 | apt-get install -y --no-install-recommends ca-certificates=20180409 && \ 17 | apt-get clean && \ 18 | rm -rf /var/lib/apt/lists/* 19 | 20 | WORKDIR /app 21 | ENV PATH="/app:${PATH}" 22 | 23 | COPY --from=build /app/bin/mesg-cli . 24 | COPY --from=build /app/bin/mesg-daemon . 25 | 26 | CMD ["mesg-daemon", "start"] 27 | -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | ARG from 2 | FROM $from 3 | 4 | COPY ./dev-chain/cli /root/.mesg-cli 5 | COPY ./dev-chain/validator /root/.mesg-node 6 | COPY ./scripts/dev-starter.sh . 7 | 8 | CMD ["bash", "dev-starter.sh"] 9 | -------------------------------------------------------------------------------- /Dockerfile.tools: -------------------------------------------------------------------------------- 1 | # base Go image version. 2 | FROM golang:1.13.10 3 | 4 | WORKDIR /project 5 | 6 | # install some dependencies from apt-get. 7 | RUN apt-get update -y && \ 8 | apt-get install -y unzip && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | # protobuf(protoc) version. 12 | ARG protobuf=3.11.4 13 | ARG gogoprotobuf=1.3.1 14 | 15 | # install protobuf(protoc). 16 | RUN wget -q https://github.com/protocolbuffers/protobuf/releases/download/v$protobuf/protoc-$protobuf-linux-x86_64.zip -O /tmp/protobuf.zip && \ 17 | mkdir /tmp/protobuf && \ 18 | unzip /tmp/protobuf.zip -d /tmp/protobuf && \ 19 | mv /tmp/protobuf/bin/* /usr/local/bin/ && \ 20 | mv /tmp/protobuf/include/* /usr/local/include/ && \ 21 | rm -rf /tmp/protobuf 22 | 23 | RUN cd /tmp/ && \ 24 | git clone https://github.com/gogo/protobuf.git && \ 25 | cd protobuf && \ 26 | make install && \ 27 | mkdir -p /usr/local/include/gogo/protobuf/ && \ 28 | cp gogoproto/gogo.proto /usr/local/include/gogo/protobuf/ 29 | 30 | # download gogo proto files 31 | RUN mkdir -p /usr/local/include/gogo/protobuf/ && \ 32 | wget -qO- https://github.com/gogo/protobuf/archive/v${gogoprotobuf}.tar.gz | tar -xzf - protobuf-${gogoprotobuf}/gogoproto/gogo.proto && \ 33 | mv protobuf-${gogoprotobuf}/gogoproto /usr/local/include/gogo/protobuf/ 34 | 35 | # install dependencies 36 | COPY go.mod go.sum ./ 37 | RUN go mod download 38 | 39 | RUN go install github.com/golang/protobuf/protoc-gen-go 40 | RUN go install github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc 41 | 42 | # verify that mesg-dev container is being used. 43 | ENV MESG_DEV true 44 | -------------------------------------------------------------------------------- /cmd/mesg-cli/serve.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "time" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | "github.com/cosmos/cosmos-sdk/client/context" 11 | "github.com/cosmos/cosmos-sdk/client/flags" 12 | "github.com/cosmos/cosmos-sdk/codec" 13 | "github.com/cosmos/cosmos-sdk/server" 14 | authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" 15 | "github.com/gorilla/mux" 16 | "github.com/mesg-foundation/engine/app" 17 | "github.com/mesg-foundation/engine/cosmos" 18 | "github.com/spf13/cobra" 19 | "github.com/spf13/viper" 20 | "github.com/tendermint/tendermint/libs/log" 21 | rpcserver "github.com/tendermint/tendermint/rpc/lib/server" 22 | ) 23 | 24 | // ServeCommand creates and starts the LCD server 25 | // adapted version of function from https://github.com/cosmos/cosmos-sdk/blob/v0.38.3/client/lcd/root.go#L74-L100 26 | func ServeCommand(cdc *codec.Codec) *cobra.Command { 27 | cmd := &cobra.Command{ 28 | Use: "rest-server", 29 | Short: "Start LCD (light-client daemon), a local REST server", 30 | RunE: func(cmd *cobra.Command, args []string) (err error) { 31 | // new rest server 32 | r := mux.NewRouter() 33 | cliCtx := context.NewCLIContext().WithCodec(cdc) 34 | logger := log.NewTMJSONLogger(log.NewSyncWriter(os.Stdout)).With("module", "rest-server") 35 | 36 | // register routes 37 | client.RegisterRoutes(cliCtx, r) 38 | authrest.RegisterTxRoutes(cliCtx, r) 39 | app.ModuleBasics.RegisterRESTRoutes(cliCtx, r) 40 | cosmos.RegisterSimulateRoute(cliCtx, r) 41 | 42 | // start 43 | var listener net.Listener 44 | server.TrapSignal(func() { 45 | err := listener.Close() 46 | logger.Error("error closing listener", "err", err) 47 | }) 48 | 49 | cfg := rpcserver.DefaultConfig() 50 | cfg.MaxOpenConnections = viper.GetInt(flags.FlagMaxOpenConnections) 51 | cfg.ReadTimeout = time.Duration(uint(viper.GetInt(flags.FlagRPCReadTimeout))) * time.Second 52 | cfg.WriteTimeout = time.Duration(uint(viper.GetInt(flags.FlagRPCWriteTimeout))) * time.Second 53 | 54 | listener, err = rpcserver.Listen(viper.GetString(flags.FlagListenAddr), cfg) 55 | if err != nil { 56 | return 57 | } 58 | logger.Info( 59 | fmt.Sprintf( 60 | "Starting application REST service (chain-id: %q)...", 61 | viper.GetString(flags.FlagChainID), 62 | ), 63 | ) 64 | 65 | return rpcserver.StartHTTPServer(listener, r, logger, cfg) 66 | }, 67 | } 68 | 69 | return flags.RegisterRestServerFlags(cmd) 70 | } 71 | -------------------------------------------------------------------------------- /cosmos/config.go: -------------------------------------------------------------------------------- 1 | package cosmos 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/crypto/keys" 5 | sdktypes "github.com/cosmos/cosmos-sdk/types" 6 | ) 7 | 8 | const ( 9 | // CosmosBech32MainPrefix defines the main Bech32 prefix. 10 | CosmosBech32MainPrefix = "mesg" 11 | 12 | // CosmosCoinType is the mesg registered coin type from https://github.com/satoshilabs/slips/blob/master/slip-0044.md. 13 | CosmosCoinType = uint32(470) 14 | 15 | // FullFundraiserPath is the parts of the BIP44 HD path that are fixed by what we used during the fundraiser. 16 | FullFundraiserPath = "44'/470'/0'/0/0" 17 | 18 | // GasAdjustment is a multiplier to make sure transactions have enough gas when gas are estimated. 19 | GasAdjustment = 1.5 20 | 21 | // DefaultAlgo for create account. 22 | DefaultAlgo = keys.Secp256k1 23 | ) 24 | 25 | // InitConfig sets the bech32 prefix and HDPath to cosmos config. 26 | func InitConfig() { 27 | // See github.com/cosmos/cosmos-sdk/types/address.go 28 | const ( 29 | // bech32PrefixAccAddr defines the Bech32 prefix of an account's address 30 | bech32PrefixAccAddr = CosmosBech32MainPrefix 31 | // bech32PrefixAccPub defines the Bech32 prefix of an account's public key 32 | bech32PrefixAccPub = CosmosBech32MainPrefix + sdktypes.PrefixPublic 33 | // bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address 34 | bech32PrefixValAddr = CosmosBech32MainPrefix + sdktypes.PrefixValidator + sdktypes.PrefixOperator 35 | // bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key 36 | bech32PrefixValPub = CosmosBech32MainPrefix + sdktypes.PrefixValidator + sdktypes.PrefixOperator + sdktypes.PrefixPublic 37 | // bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address 38 | bech32PrefixConsAddr = CosmosBech32MainPrefix + sdktypes.PrefixValidator + sdktypes.PrefixConsensus 39 | // bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key 40 | bech32PrefixConsPub = CosmosBech32MainPrefix + sdktypes.PrefixValidator + sdktypes.PrefixConsensus + sdktypes.PrefixPublic 41 | ) 42 | 43 | cfg := sdktypes.GetConfig() 44 | cfg.SetBech32PrefixForAccount(bech32PrefixAccAddr, bech32PrefixAccPub) 45 | cfg.SetBech32PrefixForValidator(bech32PrefixValAddr, bech32PrefixValPub) 46 | cfg.SetBech32PrefixForConsensusNode(bech32PrefixConsAddr, bech32PrefixConsPub) 47 | cfg.SetFullFundraiserPath(FullFundraiserPath) 48 | cfg.SetCoinType(CosmosCoinType) 49 | cfg.Seal() 50 | } 51 | -------------------------------------------------------------------------------- /cosmos/keybase_test.go: -------------------------------------------------------------------------------- 1 | package cosmos 2 | 3 | import ( 4 | "crypto/sha256" 5 | "io/ioutil" 6 | "os" 7 | "testing" 8 | 9 | "github.com/cosmos/cosmos-sdk/crypto/keys" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestKeybase(t *testing.T) { 14 | path, _ := ioutil.TempDir("", "TestKeybase") 15 | defer os.RemoveAll(path) 16 | kb, err := NewKeybase(path) 17 | require.NoError(t, err) 18 | 19 | var ( 20 | name = "name" 21 | password = "password" 22 | mnemonic = "" 23 | ) 24 | 25 | t.Run("Mnemonic", func(t *testing.T) { 26 | mnemonic, err = kb.NewMnemonic() 27 | require.NoError(t, err) 28 | }) 29 | 30 | t.Run("Create", func(t *testing.T) { 31 | acc, err := kb.CreateAccount(name, mnemonic, "", password, keys.CreateHDPath(0, 0).String(), DefaultAlgo) 32 | require.NoError(t, err) 33 | require.Equal(t, name, acc.GetName()) 34 | }) 35 | 36 | t.Run("Exist", func(t *testing.T) { 37 | exist, err := kb.Exist(name) 38 | require.NoError(t, err) 39 | require.True(t, exist) 40 | 41 | exist, err = kb.Exist("random") 42 | require.NoError(t, err) 43 | require.False(t, exist) 44 | }) 45 | 46 | t.Run("Sign", func(t *testing.T) { 47 | name2 := "name2" 48 | mnemonic2, _ := kb.NewMnemonic() 49 | _, err := kb.CreateAccount(name2, mnemonic2, "", password, keys.CreateHDPath(0, 0).String(), DefaultAlgo) 50 | require.NoError(t, err) 51 | hash := sha256.Sum256([]byte(name + ":" + password)) 52 | hash2 := sha256.Sum256([]byte(name2 + ":" + password)) 53 | for i := 0; i < 1000; i++ { 54 | nameToUse := name 55 | if i%2 == 0 { 56 | nameToUse = name2 57 | } 58 | sig, pub, err := kb.Sign(nameToUse, password, []byte{}) 59 | require.NoError(t, err) 60 | require.NotEmpty(t, sig) 61 | require.NotEmpty(t, pub) 62 | } 63 | require.NotEmpty(t, kb.privKeysCache[hash]) 64 | require.NotEmpty(t, kb.privKeysCache[hash2]) 65 | require.NotEqual(t, kb.privKeysCache[hash], kb.privKeysCache[hash2]) 66 | }) 67 | } 68 | -------------------------------------------------------------------------------- /cosmos/simulate.go: -------------------------------------------------------------------------------- 1 | package cosmos 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gorilla/mux" 7 | 8 | "github.com/cosmos/cosmos-sdk/client/context" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | "github.com/cosmos/cosmos-sdk/types/rest" 11 | "github.com/cosmos/cosmos-sdk/x/auth/client/utils" 12 | ) 13 | 14 | // RegisterSimulateRoute registers the route on the router. 15 | func RegisterSimulateRoute(cliCtx context.CLIContext, r *mux.Router) { 16 | r.HandleFunc("/txs/simulate", SimulateRequestHandlerFn(cliCtx)).Methods("POST") 17 | } 18 | 19 | // SimulateReq defines the properties of a send request's body. 20 | type SimulateReq struct { 21 | BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` 22 | Msgs []sdk.Msg `json:"msgs" yaml:"msgs"` 23 | } 24 | 25 | // SimulateRequestHandlerFn - http request handler to simulate msgs. 26 | func SimulateRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { 27 | return func(w http.ResponseWriter, r *http.Request) { 28 | var req SimulateReq 29 | if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { 30 | return 31 | } 32 | 33 | req.BaseReq = req.BaseReq.Sanitize() 34 | if !req.BaseReq.ValidateBasic(w) { 35 | return 36 | } 37 | 38 | // force simulate to true to use the following function in simulate only mode. 39 | req.BaseReq.Simulate = true 40 | utils.WriteGenerateStdTxResponse(w, cliCtx, req.BaseReq, req.Msgs) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /dev-chain/README.md: -------------------------------------------------------------------------------- 1 | # Dev chain 2 | 3 | For local use only. 4 | 5 | ## Genesis file 6 | 7 | See file `dev-genesis.json` 8 | 9 | ## Accounts 10 | 11 | ### Validator 12 | 13 | Address: `mesg10cjcxje0jjdxzdq5hpqa4dc4znhuxsax2zh7mp` 14 | Validator address: `mesgvaloper10cjcxje0jjdxzdq5hpqa4dc4znhuxsaxkrzt5d` 15 | Pubkey: `mesgpub1addwnpepq0gwhzul5qcycxxs6r7jdzdn5q29mj2a8gmngfrcfa6l8qs2dar4s2jqycv` 16 | Mnemonic: `fruit lock run bike eyebrow unique embrace cost parade welcome more frown oxygen crane club donate grid harsh marriage host skirt sign warfare cup` 17 | Coins: 100000000stake (but used in gentx) 18 | 19 | ### CLI 20 | 21 | Address: `mesg1s6mqusxaq93d70jeekqehg7aepwt7zs306ctq7` 22 | Pubkey: `mesgpub1addwnpepqvdrcdvg3x4tf0y5aapn47njxapdu4l0jgsjzcm2klp9a7eztva66eqnadt` 23 | Mnemonic: `spike raccoon obscure program raw large unaware dragon hamster round artist case fall wage sample velvet robust legend identify innocent film coral picture organ` 24 | Coins: 1000000000000000000000000atto and 1000000000stake 25 | 26 | ### Orchestrator 27 | 28 | Address: `mesg1t9h20sn3lk2jdnak5eea4lkqxkpwyfaadtqk4t` 29 | Pubkey: `mesgpub1addwnpepqde3ek5edcpxded9w2rw05jm4z3my57f7dey5pwz8hs0uzw0c3xusqmd53d` 30 | Mnemonic: `neutral false together tattoo matrix stamp poem mouse chair chair grain pledge mandate layer shiver embark struggle vicious antenna total faith genre valley mandate` 31 | Coins: 1000000000000000000000000atto 32 | -------------------------------------------------------------------------------- /dev-chain/cli/config/config.toml: -------------------------------------------------------------------------------- 1 | trust-node = "true" 2 | chain-id = "mesg-dev-chain" 3 | 4 | # orchestrtor 5 | authorized-pubkeys = "mesgpub1addwnpepqvdrcdvg3x4tf0y5aapn47njxapdu4l0jgsjzcm2klp9a7eztva66eqnadt" 6 | mnemonic = "neutral false together tattoo matrix stamp poem mouse chair chair grain pledge mandate layer shiver embark struggle vicious antenna total faith genre valley mandate" 7 | gas-prices = "" 8 | -------------------------------------------------------------------------------- /dev-chain/validator/config/app.toml: -------------------------------------------------------------------------------- 1 | # The minimum gas prices a validator is willing to accept for processing a 2 | # transaction. A transaction's fees must meet the minimum of any denomination 3 | # specified in this config (e.g. 0.25token1;0.0001token2). 4 | minimum-gas-prices = "" 5 | -------------------------------------------------------------------------------- /dev-chain/validator/config/config.toml: -------------------------------------------------------------------------------- 1 | moniker = "developer" 2 | [rpc] 3 | laddr = "tcp://0.0.0.0:26657" 4 | max_subscriptions_per_client = 100 5 | [consensus] 6 | timeout_commit = "1s" 7 | [p2p] 8 | addr_book_strict = false 9 | [instrumentation] 10 | prometheus = true 11 | [tx_index] 12 | index_all_keys = true 13 | -------------------------------------------------------------------------------- /dev-chain/validator/config/node_key.json: -------------------------------------------------------------------------------- 1 | {"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"WnB/ngV9sCHm6WruylEat+XRbmhnJ1dgTdAPIIHWiKVeZeftLREe8aUjz7+2QKdKQkJwovw3b0rFa2Z+Z2zLXw=="}} -------------------------------------------------------------------------------- /dev-chain/validator/config/priv_validator_key.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "AE7AAC113558ABD2B3D24EDC3774FBE7027F1F35", 3 | "pub_key": { 4 | "type": "tendermint/PubKeyEd25519", 5 | "value": "hvkWnhISUYLdhS1qetr6R52reu7ugi0RZjm+9XHsN7g=" 6 | }, 7 | "priv_key": { 8 | "type": "tendermint/PrivKeyEd25519", 9 | "value": "O8EZc8rbvs5H4+fdFX3uIzxULm4c6/Yxl5+9yIqkc36G+RaeEhJRgt2FLWp62vpHnat67u6CLRFmOb71cew3uA==" 10 | } 11 | } -------------------------------------------------------------------------------- /dev-chain/validator/data/priv_validator_state.json: -------------------------------------------------------------------------------- 1 | { 2 | "height": "0", 3 | "round": "0", 4 | "step": 0 5 | } -------------------------------------------------------------------------------- /e2e/account_sequence_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/x/bank" 8 | "github.com/stretchr/testify/require" 9 | "github.com/tendermint/tendermint/crypto" 10 | ) 11 | 12 | func testAccountSequence(t *testing.T) { 13 | var ( 14 | randomAddress = sdk.AccAddress(crypto.AddressHash([]byte("hello"))) 15 | err error 16 | ) 17 | t.Run("wrong msg", func(t *testing.T) { 18 | _, err = lcd.BroadcastMsg(bank.NewMsgSend( 19 | cliAddress, 20 | randomAddress, 21 | sdk.NewCoins(sdk.NewInt64Coin("wrong", 1000)), 22 | )) 23 | require.Error(t, err) 24 | require.Contains(t, err.Error(), "transaction returned with invalid code") 25 | }) 26 | t.Run("good msg", func(t *testing.T) { 27 | _, err = lcd.BroadcastMsg(bank.NewMsgSend( 28 | cliAddress, 29 | randomAddress, 30 | sdk.NewCoins(sdk.NewInt64Coin("atto", 1000)), 31 | )) 32 | require.NoError(t, err) 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /e2e/credit_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/x/auth" 8 | creditmodule "github.com/mesg-foundation/engine/x/credit" 9 | "github.com/stretchr/testify/require" 10 | "github.com/tendermint/tendermint/crypto" 11 | ) 12 | 13 | func testCredit(t *testing.T) { 14 | var ( 15 | newAddr = sdk.AccAddress(crypto.AddressHash([]byte("addr"))) 16 | ) 17 | t.Run("account does not exist", func(t *testing.T) { 18 | var accR *auth.BaseAccount 19 | require.NoError(t, lcd.Get("auth/accounts/"+newAddr.String(), &accR)) 20 | require.True(t, accR.Address.Empty()) 21 | }) 22 | t.Run("add 1000 credits", func(t *testing.T) { 23 | t.Run("balance before", func(t *testing.T) { 24 | var balance sdk.Int 25 | require.NoError(t, lcd.Get("credit/get/"+newAddr.String(), &balance)) 26 | require.Equal(t, sdk.NewInt(0), balance) 27 | }) 28 | t.Run("add credits", func(t *testing.T) { 29 | msg := creditmodule.MsgAdd{ 30 | Signer: cliAddress, 31 | Address: newAddr, 32 | Amount: sdk.NewInt(1000), 33 | } 34 | _, err = lcd.BroadcastMsg(msg) 35 | require.NoError(t, err) 36 | }) 37 | t.Run("balance after", func(t *testing.T) { 38 | var balance sdk.Int 39 | require.NoError(t, lcd.Get("credit/get/"+newAddr.String(), &balance)) 40 | require.Equal(t, sdk.NewInt(1000), balance) 41 | }) 42 | }) 43 | t.Run("account exists", func(t *testing.T) { 44 | var accR *auth.BaseAccount 45 | require.NoError(t, lcd.Get("auth/accounts/"+newAddr.String(), &accR)) 46 | require.False(t, accR.Address.Empty()) 47 | }) 48 | t.Run("not authorized", func(t *testing.T) { 49 | msg := creditmodule.MsgAdd{ 50 | Signer: engineAddress, 51 | Address: newAddr, 52 | Amount: sdk.NewInt(1000), 53 | } 54 | _, err = lcdEngine.BroadcastMsg(msg) 55 | require.EqualError(t, err, "transaction returned with invalid code 4: unauthorized: the signer is not a minter: failed to execute message; message index: 0") 56 | }) 57 | } 58 | -------------------------------------------------------------------------------- /e2e/instance_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/mesg-foundation/engine/hash" 7 | "github.com/mesg-foundation/engine/instance" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | var testInstanceHash hash.Hash 12 | 13 | func testInstance(t *testing.T) { 14 | t.Run("get", func(t *testing.T) { 15 | var inst *instance.Instance 16 | require.NoError(t, lcd.Get("instance/get/"+testInstanceHash.String(), &inst)) 17 | require.Equal(t, testInstanceHash, inst.Hash) 18 | require.Equal(t, testServiceHash, inst.ServiceHash) 19 | require.Equal(t, hash.Dump([]string{"BAR=3", "FOO=1", "REQUIRED=4"}), inst.EnvHash) 20 | }) 21 | 22 | t.Run("list", func(t *testing.T) { 23 | insts := make([]*instance.Instance, 0) 24 | require.NoError(t, lcd.Get("instance/list", &insts)) 25 | require.Len(t, insts, 1) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /e2e/orchestrator_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func testOrchestrator(t *testing.T) { 8 | // running orchestrator tests 9 | t.Run("process balance and withdraw", testOrchestratorProcessBalanceWithdraw(testRunnerHash, testInstanceHash)) 10 | t.Run("event task", testOrchestratorEventTask(testRunnerHash, testInstanceHash)) 11 | t.Run("result task", testOrchestratorResultTask(testRunnerHash, testInstanceHash)) 12 | t.Run("map const", testOrchestratorMapConst(testRunnerHash, testInstanceHash)) 13 | t.Run("ref grand parent task", testOrchestratorRefGrandParentTask(testRunnerHash, testInstanceHash)) 14 | t.Run("nested data", testOrchestratorNestedData(testRunnerHash, testInstanceHash)) 15 | t.Run("nested map", testOrchestratorNestedMap(testRunnerHash, testInstanceHash)) 16 | t.Run("ref path nested", testOrchestratorRefPathNested(testRunnerHash, testInstanceHash)) 17 | t.Run("filter", testOrchestratorFilter(testRunnerHash, testInstanceHash)) 18 | t.Run("filter path nested", testOrchestratorFilterPathNested(testRunnerHash, testInstanceHash)) 19 | } 20 | -------------------------------------------------------------------------------- /e2e/service_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/mesg-foundation/engine/hash" 8 | "github.com/mesg-foundation/engine/ownership" 9 | "github.com/mesg-foundation/engine/service" 10 | servicerest "github.com/mesg-foundation/engine/x/service/client/rest" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | var ( 15 | testServiceHash hash.Hash 16 | testServiceAddress sdk.AccAddress 17 | testServiceStruct *service.Service 18 | err error 19 | ) 20 | 21 | func testService(t *testing.T) { 22 | t.Run("create", func(t *testing.T) { 23 | testCreateServiceMsg.Owner = cliAddress 24 | testServiceHash, err = lcd.BroadcastMsg(testCreateServiceMsg) 25 | require.NoError(t, err) 26 | }) 27 | 28 | t.Run("get", func(t *testing.T) { 29 | require.NoError(t, lcd.Get("service/get/"+testServiceHash.String(), &testServiceStruct)) 30 | require.Equal(t, testServiceHash, testServiceStruct.Hash) 31 | testServiceAddress = testServiceStruct.Address 32 | }) 33 | 34 | t.Run("list", func(t *testing.T) { 35 | ss := make([]*service.Service, 0) 36 | require.NoError(t, lcd.Get("service/list", &ss)) 37 | require.Len(t, ss, 1) 38 | }) 39 | 40 | t.Run("exists", func(t *testing.T) { 41 | var exist bool 42 | require.NoError(t, lcd.Get("service/exist/"+testServiceHash.String(), &exist)) 43 | require.True(t, exist) 44 | require.NoError(t, lcd.Get("service/exist/"+hash.Int(1).String(), &exist)) 45 | require.False(t, exist) 46 | }) 47 | 48 | t.Run("hash", func(t *testing.T) { 49 | msg := servicerest.HashRequest{ 50 | Sid: testCreateServiceMsg.Sid, 51 | Name: testCreateServiceMsg.Name, 52 | Description: testCreateServiceMsg.Description, 53 | Configuration: testCreateServiceMsg.Configuration, 54 | Tasks: testCreateServiceMsg.Tasks, 55 | Events: testCreateServiceMsg.Events, 56 | Dependencies: testCreateServiceMsg.Dependencies, 57 | Repository: testCreateServiceMsg.Repository, 58 | Source: testCreateServiceMsg.Source, 59 | } 60 | var hash hash.Hash 61 | require.NoError(t, lcd.Post("service/hash", msg, &hash)) 62 | require.Equal(t, testServiceHash, hash) 63 | }) 64 | 65 | t.Run("check ownership creation", func(t *testing.T) { 66 | ownerships := make([]*ownership.Ownership, 0) 67 | require.NoError(t, lcd.Get("ownership/list", &ownerships)) 68 | require.Len(t, ownerships, 1) 69 | require.NotEmpty(t, ownerships[0].Owner) 70 | require.Equal(t, ownership.Ownership_Service, ownerships[0].Resource) 71 | require.Equal(t, testServiceHash, ownerships[0].ResourceHash) 72 | }) 73 | } 74 | -------------------------------------------------------------------------------- /e2e/testdata/test-complex-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.13 2 | WORKDIR /app 3 | COPY go.mod go.sum ./ 4 | RUN go mod download 5 | COPY . . 6 | RUN go build -o "mesg-test" 7 | CMD [ "./mesg-test" ] 8 | -------------------------------------------------------------------------------- /e2e/testdata/test-complex-service/go.mod: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/mesg-foundation/engine v0.18.4-0.20200406120519-06c3e44902e9 7 | google.golang.org/grpc v1.28.0 8 | ) 9 | -------------------------------------------------------------------------------- /e2e/testdata/test-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.13 2 | WORKDIR /app 3 | COPY go.mod go.sum ./ 4 | RUN go mod download 5 | COPY . . 6 | RUN go build -o "mesg-test" 7 | CMD [ "./mesg-test" ] 8 | -------------------------------------------------------------------------------- /e2e/testdata/test-service/go.mod: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/mesg-foundation/engine v0.18.4-0.20200406120519-06c3e44902e9 7 | google.golang.org/grpc v1.28.0 8 | ) 9 | -------------------------------------------------------------------------------- /event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/hash" 5 | "github.com/mesg-foundation/engine/protobuf/types" 6 | ) 7 | 8 | // New creates an event eventKey with eventData for service s. 9 | func New(instanceHash hash.Hash, eventKey string, eventData *types.Struct) *Event { 10 | e := &Event{ 11 | InstanceHash: instanceHash, 12 | Key: eventKey, 13 | Data: eventData, 14 | } 15 | e.Hash = hash.Dump(e) 16 | return e 17 | } 18 | -------------------------------------------------------------------------------- /event/event_listener.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/cskr/pubsub" 5 | "github.com/mesg-foundation/engine/hash" 6 | ) 7 | 8 | // Filter store fileds for matching events. 9 | type Filter struct { 10 | Hash hash.Hash 11 | InstanceHash hash.Hash 12 | Key string 13 | } 14 | 15 | // Match matches event. 16 | func (f *Filter) Match(e *Event) bool { 17 | if f == nil { 18 | return true 19 | } 20 | 21 | if !f.Hash.IsZero() && !f.Hash.Equal(e.Hash) { 22 | return false 23 | } 24 | 25 | if !f.InstanceHash.IsZero() && !f.InstanceHash.Equal(e.InstanceHash) { 26 | return false 27 | } 28 | 29 | if f.Key != "" && f.Key != "*" && f.Key != e.Key { 30 | return false 31 | } 32 | 33 | return true 34 | } 35 | 36 | // HasKey returns true if key is set to specified value. 37 | func (f *Filter) HasKey() bool { 38 | return f != nil && f.Key != "" && f.Key != "*" 39 | } 40 | 41 | // Listener provides functionalities to listen MESG events. 42 | type Listener struct { 43 | C chan *Event 44 | 45 | ps *pubsub.PubSub 46 | topic string 47 | c chan interface{} 48 | 49 | filter *Filter 50 | } 51 | 52 | // NewListener creates a new Listener with given sdk and filters. 53 | func NewListener(ps *pubsub.PubSub, topic string, f *Filter) *Listener { 54 | return &Listener{ 55 | C: make(chan *Event, 1), 56 | ps: ps, 57 | topic: topic, 58 | c: ps.Sub(topic), 59 | filter: f, 60 | } 61 | } 62 | 63 | // Close stops listening for events. 64 | func (l *Listener) Close() { 65 | go func() { 66 | l.ps.Unsub(l.c, l.topic) 67 | close(l.C) 68 | }() 69 | } 70 | 71 | // Listen listens events that match filter. 72 | func (l *Listener) Listen() { 73 | for v := range l.c { 74 | if e := v.(*Event); l.filter.Match(e) { 75 | l.C <- e 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /event/event_listener_test.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/cskr/pubsub" 7 | "github.com/mesg-foundation/engine/hash" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestFilter(t *testing.T) { 12 | var tests = []struct { 13 | f *Filter 14 | e *Event 15 | match bool 16 | }{ 17 | { 18 | nil, 19 | nil, 20 | true, 21 | }, 22 | { 23 | &Filter{}, 24 | &Event{}, 25 | true, 26 | }, 27 | { 28 | &Filter{Hash: hash.Int(1)}, 29 | &Event{Hash: hash.Int(1)}, 30 | true, 31 | }, 32 | { 33 | &Filter{Hash: hash.Int(1)}, 34 | &Event{Hash: hash.Int(2)}, 35 | false, 36 | }, 37 | { 38 | &Filter{InstanceHash: hash.Int(1)}, 39 | &Event{InstanceHash: hash.Int(1)}, 40 | true, 41 | }, 42 | { 43 | &Filter{InstanceHash: hash.Int(1)}, 44 | &Event{InstanceHash: hash.Int(1)}, 45 | true, 46 | }, 47 | { 48 | &Filter{Key: "0"}, 49 | &Event{Key: "0"}, 50 | true, 51 | }, 52 | { 53 | &Filter{Key: "*"}, 54 | &Event{Key: "0"}, 55 | true, 56 | }, 57 | { 58 | &Filter{Key: "0"}, 59 | &Event{Key: "1"}, 60 | false, 61 | }, 62 | } 63 | 64 | for _, tt := range tests { 65 | assert.Equal(t, tt.match, tt.f.Match(tt.e)) 66 | } 67 | } 68 | 69 | func TestEventListener(t *testing.T) { 70 | topic := "test-topic" 71 | testEvent := &Event{Key: "0"} 72 | ps := pubsub.New(0) 73 | el := NewListener(ps, topic, &Filter{Key: "0"}) 74 | 75 | go func() { 76 | ps.Pub(&Event{Key: "1"}, topic) 77 | ps.Pub(testEvent, topic) 78 | }() 79 | go el.Listen() 80 | 81 | recvEvent := <-el.C 82 | assert.Equal(t, testEvent, recvEvent) 83 | 84 | el.Close() 85 | _, ok := <-el.C 86 | assert.False(t, ok) 87 | } 88 | -------------------------------------------------------------------------------- /event/publisher/publisher.go: -------------------------------------------------------------------------------- 1 | package publisher 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cskr/pubsub" 7 | "github.com/mesg-foundation/engine/cosmos" 8 | "github.com/mesg-foundation/engine/event" 9 | "github.com/mesg-foundation/engine/hash" 10 | "github.com/mesg-foundation/engine/instance" 11 | "github.com/mesg-foundation/engine/protobuf/types" 12 | "github.com/mesg-foundation/engine/service" 13 | instancemodule "github.com/mesg-foundation/engine/x/instance" 14 | servicemodule "github.com/mesg-foundation/engine/x/service" 15 | ) 16 | 17 | const ( 18 | // streamTopic is topic used to broadcast events. 19 | streamTopic = "event-stream" 20 | ) 21 | 22 | // EventPublisher exposes event APIs of MESG. 23 | type EventPublisher struct { 24 | ps *pubsub.PubSub 25 | rpc *cosmos.RPC 26 | } 27 | 28 | // New creates a new Event SDK with given options. 29 | func New(rpc *cosmos.RPC) *EventPublisher { 30 | return &EventPublisher{ 31 | ps: pubsub.New(0), 32 | rpc: rpc, 33 | } 34 | } 35 | 36 | // Publish a MESG event eventKey with eventData for service token. 37 | func (ep *EventPublisher) Publish(instanceHash hash.Hash, eventKey string, eventData *types.Struct) (*event.Event, error) { 38 | var i *instance.Instance 39 | route := fmt.Sprintf("custom/%s/%s/%s", instancemodule.QuerierRoute, instancemodule.QueryGet, instanceHash) 40 | if err := ep.rpc.QueryJSON(route, nil, &i); err != nil { 41 | return nil, err 42 | } 43 | 44 | var s *service.Service 45 | route = fmt.Sprintf("custom/%s/%s/%s", servicemodule.QuerierRoute, servicemodule.QueryGet, i.ServiceHash) 46 | if err := ep.rpc.QueryJSON(route, nil, &s); err != nil { 47 | return nil, err 48 | } 49 | 50 | if err := s.RequireEventData(eventKey, eventData); err != nil { 51 | return nil, err 52 | } 53 | 54 | e := event.New(instanceHash, eventKey, eventData) 55 | go ep.ps.Pub(e, streamTopic) 56 | return e, nil 57 | } 58 | 59 | // GetStream broadcasts all events. 60 | func (ep *EventPublisher) GetStream(f *event.Filter) *event.Listener { 61 | l := event.NewListener(ep.ps, streamTopic, f) 62 | go l.Listen() 63 | return l 64 | } 65 | -------------------------------------------------------------------------------- /execution/error.go: -------------------------------------------------------------------------------- 1 | package execution 2 | 3 | import "fmt" 4 | 5 | // StatusError is an error when the processing is done on en execution with the wrong status 6 | type StatusError struct { 7 | ExpectedStatus Status 8 | ActualStatus Status 9 | } 10 | 11 | // Error returns the string representation of error. 12 | func (e StatusError) Error() string { 13 | return fmt.Sprintf("Execution status error: %q instead of %q", e.ActualStatus, e.ExpectedStatus) 14 | } 15 | -------------------------------------------------------------------------------- /execution/sort.go: -------------------------------------------------------------------------------- 1 | package execution 2 | 3 | // ByBlockHeight implements sort.Interface for []*Execution based on the block height field. 4 | type ByBlockHeight []*Execution 5 | 6 | func (a ByBlockHeight) Len() int { return len(a) } 7 | func (a ByBlockHeight) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 8 | func (a ByBlockHeight) Less(i, j int) bool { return a[i].BlockHeight < a[j].BlockHeight } 9 | -------------------------------------------------------------------------------- /ext/xerrors/errors.go: -------------------------------------------------------------------------------- 1 | package xerrors 2 | 3 | import ( 4 | "strings" 5 | "sync" 6 | ) 7 | 8 | // Errors is an error for tracing multiple errors. 9 | type Errors []error 10 | 11 | // ErrorOrNil returns an error if there is more then 0 error, nil otherwise. 12 | func (e Errors) ErrorOrNil() error { 13 | if len(e) == 0 { 14 | return nil 15 | } 16 | return e 17 | } 18 | 19 | func (e Errors) Error() string { 20 | var s []string 21 | for _, err := range e { 22 | if err != nil { 23 | s = append(s, err.Error()) 24 | } 25 | } 26 | return strings.Join(s, ". ") 27 | } 28 | 29 | // SyncErrors is an error for tracing multiple errors safe to use in multiple goroutines. 30 | type SyncErrors struct { 31 | mx sync.Mutex 32 | Errors 33 | } 34 | 35 | // Append appends given err. 36 | func (e *SyncErrors) Append(err error) { 37 | e.mx.Lock() 38 | e.Errors = append(e.Errors, err) 39 | e.mx.Unlock() 40 | } 41 | -------------------------------------------------------------------------------- /ext/xerrors/errors_test.go: -------------------------------------------------------------------------------- 1 | package xerrors 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | ) 7 | 8 | func TestAppend(t *testing.T) { 9 | var errs Errors 10 | errs = append(errs, errors.New("a")) 11 | errs = append(errs, errors.New("b")) 12 | if len(errs) != 2 { 13 | t.Fatalf("invalid errors count - got: %d, want: 2", len(errs)) 14 | } 15 | } 16 | 17 | func TestError(t *testing.T) { 18 | var errs Errors 19 | if errs.Error() != "" { 20 | t.Fatalf("invalid error message - got: %q, want: %q", errs.Error(), "") 21 | } 22 | 23 | errs = append(errs, errors.New("a")) 24 | errs = append(errs, errors.New("b")) 25 | if errs.Error() != "a. b" { 26 | t.Fatalf("invalid error message - got: %q, want: %q", errs.Error(), "a\nb") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ext/xnet/dnsclient.go: -------------------------------------------------------------------------------- 1 | // Package xnet Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | package xnet 5 | 6 | // Source: https://golang.org/src/net/dnsclient.go 7 | // IsDomainName checks if a string is a presentation-format domain name 8 | // (currently restricted to hostname-compatible "preferred name" LDH labels and 9 | // SRV-like "underscore labels"; see golang.org/issue/12421). 10 | //nolint:gocyclo 11 | func IsDomainName(s string) bool { 12 | // See RFC 1035, RFC 3696. 13 | // Presentation format has dots before every label except the first, and the 14 | // terminal empty label is optional here because we assume fully-qualified 15 | // (absolute) input. We must therefore reserve space for the first and last 16 | // labels' length octets in wire format, where they are necessary and the 17 | // maximum total length is 255. 18 | // So our _effective_ maximum is 253, but 254 is not rejected if the last 19 | // character is a dot. 20 | l := len(s) 21 | if l == 0 || l > 254 || l == 254 && s[l-1] != '.' { 22 | return false 23 | } 24 | 25 | last := byte('.') 26 | ok := false // Ok once we've seen a letter. 27 | partlen := 0 28 | for i := 0; i < len(s); i++ { 29 | c := s[i] 30 | switch { 31 | default: 32 | return false 33 | case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_': 34 | ok = true 35 | partlen++ 36 | case '0' <= c && c <= '9': 37 | // fine 38 | partlen++ 39 | case c == '-': 40 | // Byte before dash cannot be dot. 41 | if last == '.' { 42 | return false 43 | } 44 | partlen++ 45 | case c == '.': 46 | // Byte before dot cannot be dot, dash. 47 | if last == '.' || last == '-' { 48 | return false 49 | } 50 | if partlen > 63 || partlen == 0 { 51 | return false 52 | } 53 | partlen = 0 54 | } 55 | last = c 56 | } 57 | if last == '-' || partlen > 63 { 58 | return false 59 | } 60 | 61 | return ok 62 | } 63 | -------------------------------------------------------------------------------- /ext/xnet/ip_test.go: -------------------------------------------------------------------------------- 1 | package xnet 2 | 3 | import ( 4 | "net" 5 | "testing" 6 | ) 7 | 8 | func TestJoinHostPort(t *testing.T) { 9 | for _, tt := range []struct { 10 | host string 11 | port int 12 | hostPort string 13 | }{ 14 | {"localhost", 80, "localhost:80"}, 15 | } { 16 | if hostPort := JoinHostPort(tt.host, tt.port); hostPort != tt.hostPort { 17 | t.Errorf("JoinHostPort(%q, %q) = %q; want %q", tt.host, tt.port, hostPort, tt.hostPort) 18 | } 19 | } 20 | } 21 | 22 | func TestSplitHostPort(t *testing.T) { 23 | for _, tt := range []struct { 24 | hostPort string 25 | host string 26 | port int 27 | }{ 28 | {"localhost:80", "localhost", 80}, 29 | } { 30 | if host, port, err := SplitHostPort(tt.hostPort); host != tt.host || port != tt.port || err != nil { 31 | t.Errorf("SplitHostPort(%q) = %q, %q, %v; want %q, %q, nil", tt.hostPort, host, port, err, tt.host, tt.port) 32 | } 33 | } 34 | 35 | for _, tt := range []struct { 36 | hostPort string 37 | err string 38 | }{ 39 | {"localhost", "missing port in address"}, 40 | {"localhost:a", "can't parse port"}, 41 | {"localhost:-1", "port out of range"}, 42 | {"localhost:65536", "port out of range"}, 43 | } { 44 | if host, port, err := SplitHostPort(tt.hostPort); err == nil { 45 | t.Errorf("SplitHostPort(%q) should have failed", tt.hostPort) 46 | } else { 47 | e := err.(*net.AddrError) 48 | if e.Err != tt.err { 49 | t.Errorf("SplitHostPort(%q) = _, _, %q; want %q", tt.hostPort, e.Err, tt.err) 50 | } 51 | if host != "" || port != 0 { 52 | t.Errorf("SplitHostPort(%q) = %q, %q, err; want %q, %q, err on failure", tt.hostPort, host, port, "", "") 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ext/xnet/ipsock.go: -------------------------------------------------------------------------------- 1 | package xnet 2 | 3 | import ( 4 | "net" 5 | "strconv" 6 | ) 7 | 8 | // Maximum and minimum ports number. 9 | const ( 10 | MinPort = 0 11 | MaxPort = 65535 12 | ) 13 | 14 | // JoinHostPort combines host and port into a network address of the 15 | // form "host:port" or, if host contains a colon or a percent sign, 16 | // "[host]:port". 17 | func JoinHostPort(host string, port int) string { 18 | return net.JoinHostPort(host, strconv.FormatInt(int64(port), 10)) 19 | } 20 | 21 | // SplitHostPort splits a network address of the form "host:port", 22 | // "host%zone:port", "[host]:port" or "[host%zone]:port" into host or 23 | // host%zone and port. 24 | func SplitHostPort(hostport string) (string, int, error) { 25 | host, portStr, err := net.SplitHostPort(hostport) 26 | if err != nil { 27 | return "", 0, err 28 | } 29 | 30 | port, err := strconv.ParseInt(portStr, 10, 64) 31 | if err != nil { 32 | return "", 0, &net.AddrError{Err: "can't parse port", Addr: hostport} 33 | } 34 | 35 | if port < MinPort || port > MaxPort { 36 | return "", 0, &net.AddrError{Err: "port out of range", Addr: hostport} 37 | } 38 | 39 | return host, int(port), nil 40 | } 41 | -------------------------------------------------------------------------------- /ext/xos/env.go: -------------------------------------------------------------------------------- 1 | package xos 2 | 3 | import ( 4 | "sort" 5 | "strings" 6 | ) 7 | 8 | // EnvMergeSlices merges multiple slices into single one. 9 | // If the same key exist multiple time, it will be added in occurrence order. 10 | func EnvMergeSlices(values ...[]string) []string { 11 | envs := make(map[string]string) 12 | for _, value := range values { 13 | for _, v := range value { 14 | if e := strings.SplitN(v, "=", 2); len(e) == 1 { 15 | envs[e[0]] = "" 16 | } else { 17 | envs[e[0]] = e[1] 18 | } 19 | } 20 | } 21 | 22 | env := make([]string, 0, len(values)) 23 | for k, v := range envs { 24 | env = append(env, k+"="+v) 25 | } 26 | 27 | // Make sure envs are sorted to give repeatable output 28 | // It is important for hash instance calculation 29 | sort.Stable(sort.StringSlice(env)) 30 | return env 31 | } 32 | -------------------------------------------------------------------------------- /ext/xos/env_test.go: -------------------------------------------------------------------------------- 1 | package xos 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestEnvMergeSlices(t *testing.T) { 8 | values := [][]string{ 9 | {"a=1", "b=2"}, 10 | {"c=3", "a=2"}, 11 | } 12 | env := EnvMergeSlices(values...) 13 | for i, v := range []string{"a=2", "b=2", "c=3"} { 14 | if env[i] != v { 15 | t.Errorf("env slice dosen't contain %s", v) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ext/xrand/seed.go: -------------------------------------------------------------------------------- 1 | package xrand 2 | 3 | import ( 4 | crypto_rand "crypto/rand" 5 | "encoding/binary" 6 | "math/rand" 7 | "time" 8 | ) 9 | 10 | // SeedInit initialize rand package with secure random number. 11 | func SeedInit() { 12 | var b [8]byte 13 | if _, err := crypto_rand.Read(b[:]); err == nil { 14 | rand.Seed(int64(binary.LittleEndian.Uint64(b[:]))) 15 | } else { 16 | // fallback to unix nano time 17 | rand.Seed(time.Now().UTC().UnixNano()) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ext/xreflect/xreflect.go: -------------------------------------------------------------------------------- 1 | package xreflect 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | // IsNil reports whether its argument o is nil. 8 | // It traverses down to first non-pointer value. 9 | func IsNil(o interface{}) bool { 10 | if o == nil { 11 | return true 12 | } 13 | 14 | for rv := reflect.ValueOf(o); rv.Kind() == reflect.Ptr; rv = rv.Elem() { 15 | if rv.IsNil() { 16 | return true 17 | } 18 | } 19 | return false 20 | } 21 | -------------------------------------------------------------------------------- /ext/xreflect/xreflect_test.go: -------------------------------------------------------------------------------- 1 | package xreflect 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestIsNil(t *testing.T) { 9 | var tests = []struct { 10 | o interface{} 11 | name string 12 | expected bool 13 | }{ 14 | {nil, "nil", true}, 15 | {(*time.Time)(nil), "nil struct", true}, 16 | {(**time.Time)(nil), "nil nil struct", true}, 17 | {time.Time{}, "struct", false}, 18 | {&time.Time{}, "ptr struct", false}, 19 | } 20 | for _, tt := range tests { 21 | tt := tt 22 | t.Run(tt.name, func(t *testing.T) { 23 | actual := IsNil(tt.o) 24 | if actual != tt.expected { 25 | t.Errorf("(%s): expected %t, actual %t", tt.name, tt.expected, actual) 26 | } 27 | }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ext/xsignal/signal.go: -------------------------------------------------------------------------------- 1 | package xsignal 2 | 3 | import ( 4 | "os" 5 | "os/signal" 6 | "syscall" 7 | ) 8 | 9 | // WaitForInterrupt creates a read channel for catch SIGINT and SIGTERM signals. 10 | func WaitForInterrupt() chan os.Signal { 11 | abort := make(chan os.Signal, 1) 12 | signal.Notify(abort, os.Interrupt, syscall.SIGTERM) 13 | return abort 14 | } 15 | -------------------------------------------------------------------------------- /ext/xsignal/signal_test.go: -------------------------------------------------------------------------------- 1 | package xsignal 2 | 3 | import ( 4 | "os" 5 | "os/signal" 6 | "syscall" 7 | "testing" 8 | "time" 9 | ) 10 | 11 | // WaitForInterrupt creates a read channel for catch SIGINT and SIGTERM signals. 12 | func TestWaitForInterrupt(t *testing.T) { 13 | abort := WaitForInterrupt() 14 | defer signal.Stop(abort) 15 | 16 | syscall.Kill(os.Getpid(), syscall.SIGINT) 17 | select { 18 | case sig := <-abort: 19 | if sig != syscall.SIGINT { 20 | t.Fatalf("unexpected signal - got %v, want %v", sig, syscall.SIGINT) 21 | } 22 | case <-time.After(1 * time.Second): 23 | t.Fatalf("timeout waiting for signal") 24 | } 25 | 26 | syscall.Kill(os.Getpid(), syscall.SIGTERM) 27 | select { 28 | case sig := <-abort: 29 | if sig != syscall.SIGTERM { 30 | t.Fatalf("unexpected signal - got %v, want %v", sig, syscall.SIGTERM) 31 | } 32 | case <-time.After(1 * time.Second): 33 | t.Fatalf("timeout waiting for signal") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ext/xstrings/strings.go: -------------------------------------------------------------------------------- 1 | package xstrings 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "github.com/mesg-foundation/engine/ext/xrand" 7 | ) 8 | 9 | func init() { 10 | xrand.SeedInit() 11 | } 12 | 13 | // SliceContains returns true if slice a contains e element, false otherwise. 14 | func SliceContains(a []string, e string) bool { 15 | for _, s := range a { 16 | if s == e { 17 | return true 18 | } 19 | } 20 | return false 21 | } 22 | 23 | // FindLongest finds the length of longest string in slice. 24 | func FindLongest(ss []string) int { 25 | l := 0 26 | for _, s := range ss { 27 | if i := len(s); i > l { 28 | l = i 29 | } 30 | } 31 | return l 32 | } 33 | 34 | // SliceIndex returns the index e in a, return -1 if not found. 35 | func SliceIndex(a []string, e string) int { 36 | for i, s := range a { 37 | if s == e { 38 | return i 39 | } 40 | } 41 | return -1 42 | } 43 | 44 | var asciiletters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 45 | 46 | // RandASCIILetters generates random string from ascii letters. 47 | func RandASCIILetters(n int) string { 48 | b := make([]byte, n) 49 | for i := range b { 50 | b[i] = asciiletters[rand.Intn(len(asciiletters))] 51 | } 52 | return string(b) 53 | } 54 | -------------------------------------------------------------------------------- /ext/xstrings/strings_test.go: -------------------------------------------------------------------------------- 1 | package xstrings 2 | 3 | import "testing" 4 | 5 | func TestSliceContains(t *testing.T) { 6 | for _, tt := range []struct { 7 | s []string 8 | e string 9 | expected bool 10 | }{ 11 | {[]string{"a"}, "a", true}, 12 | {[]string{"a"}, "b", false}, 13 | } { 14 | if got := SliceContains(tt.s, tt.e); got != tt.expected { 15 | t.Errorf("%v slice contains %s - got %t, want %t", tt.s, tt.e, got, tt.expected) 16 | } 17 | } 18 | } 19 | 20 | func TestFindLongest(t *testing.T) { 21 | for _, tt := range []struct { 22 | s []string 23 | expected int 24 | }{ 25 | {[]string{"a"}, 1}, 26 | {[]string{"a", "aa"}, 2}, 27 | } { 28 | if got := FindLongest(tt.s); got != tt.expected { 29 | t.Errorf("%v slice find longetst - got %d, want %d", tt.s, got, tt.expected) 30 | } 31 | } 32 | } 33 | 34 | func TestSliceIndex(t *testing.T) { 35 | for _, tt := range []struct { 36 | s []string 37 | e string 38 | expected int 39 | }{ 40 | {[]string{"a"}, "b", -1}, 41 | {[]string{"a", "b"}, "a", 0}, 42 | {[]string{"a", "b"}, "b", 1}, 43 | } { 44 | if got := SliceIndex(tt.s, tt.e); got != tt.expected { 45 | t.Errorf("%v slice index %s - got %d, want %d", tt.s, tt.e, got, tt.expected) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /hash/hash_test.go: -------------------------------------------------------------------------------- 1 | package hash 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | "testing/quick" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | var ( 13 | zero = Int(0) 14 | one = Int(1) 15 | ) 16 | 17 | func TestDigest(t *testing.T) { 18 | d := New() 19 | d.Write([]byte{0}) 20 | 21 | hash := d.Sum(nil) 22 | assert.Equal(t, hash.String(), "8RBsoeyoRwajj86MZfZE6gMDJQVYGYcdSfx1zxqxNHbr") 23 | } 24 | 25 | func TestDump(t *testing.T) { 26 | assert.Equal(t, Dump(struct{}{}).String(), "5ajuwjHoLj33yG5t5UFsJtUb3vnRaJQEMPqSLz6VyoHK") 27 | } 28 | 29 | func TestInt(t *testing.T) { 30 | assert.Equal(t, uint8(1), Int(1)[0]) 31 | } 32 | 33 | func TestRandom(t *testing.T) { 34 | hash, _ := Random() 35 | assert.Len(t, hash, size) 36 | 37 | seen := make(map[string]bool) 38 | 39 | f := func() bool { 40 | hash, err := Random() 41 | if err != nil { 42 | return false 43 | } 44 | 45 | if seen[hash.String()] { 46 | return false 47 | } 48 | seen[hash.String()] = true 49 | return true 50 | } 51 | require.NoError(t, quick.Check(f, nil)) 52 | } 53 | 54 | func TestDecode(t *testing.T) { 55 | hash, err := Decode("4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM") 56 | assert.NoError(t, err) 57 | assert.Equal(t, hash, one) 58 | 59 | _, err = Decode("0") 60 | assert.Equal(t, "hash: invalid base58 digit ('0')", err.Error()) 61 | 62 | _, err = Decode("1") 63 | assert.Equal(t, "hash: invalid length", err.Error()) 64 | } 65 | 66 | func TestIsZero(t *testing.T) { 67 | assert.True(t, Hash{}.IsZero()) 68 | } 69 | 70 | func TestString(t *testing.T) { 71 | assert.Equal(t, one.String(), "4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM") 72 | } 73 | 74 | func TestEqual(t *testing.T) { 75 | assert.True(t, zero.Equal(zero)) 76 | assert.False(t, zero.Equal(one)) 77 | } 78 | 79 | func TestMarshalJSON(t *testing.T) { 80 | b, err := json.Marshal(Int(1)) 81 | assert.NoError(t, err) 82 | assert.Equal(t, "\"4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM\"", string(b)) 83 | } 84 | 85 | func TestUnmarshalJSON(t *testing.T) { 86 | var h Hash 87 | assert.NoError(t, json.Unmarshal([]byte("\"4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM\""), &h)) 88 | assert.Equal(t, Int(1), h) 89 | } 90 | -------------------------------------------------------------------------------- /instance/instance.go: -------------------------------------------------------------------------------- 1 | package instance 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/ext/xvalidator" 5 | "github.com/mesg-foundation/engine/hash" 6 | ) 7 | 8 | // New returns a new Instance and validate it. 9 | func New(serviceHash hash.Hash, envHash hash.Hash) (*Instance, error) { 10 | inst := &Instance{ 11 | ServiceHash: serviceHash, 12 | EnvHash: envHash, 13 | } 14 | inst.Hash = hash.Dump(inst) 15 | return inst, xvalidator.Struct(inst) 16 | } 17 | -------------------------------------------------------------------------------- /internal/tools/tools.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | package tools 4 | 5 | // Those imports are here to keep tools in vendor. 6 | // For more info read: https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module 7 | import ( 8 | _ "github.com/go-bindata/go-bindata/go-bindata" 9 | _ "github.com/golang/protobuf/protoc-gen-go" 10 | _ "github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc" 11 | _ "github.com/tcnksm/ghr" 12 | ) 13 | -------------------------------------------------------------------------------- /ownership/ownership.go: -------------------------------------------------------------------------------- 1 | package ownership 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/ext/xvalidator" 6 | "github.com/mesg-foundation/engine/hash" 7 | ) 8 | 9 | // New returns a new ownership and validate it. 10 | func New(owner string, resource Ownership_Resource, resourceHash hash.Hash, resourceAddress sdk.AccAddress) (*Ownership, error) { 11 | own := &Ownership{ 12 | Owner: owner, 13 | Resource: resource, 14 | ResourceHash: resourceHash, 15 | ResourceAddress: resourceAddress, 16 | } 17 | own.Hash = hash.Dump(own) 18 | return own, xvalidator.Struct(own) 19 | } 20 | -------------------------------------------------------------------------------- /process/filter.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | 7 | "github.com/mesg-foundation/engine/protobuf/types" 8 | ) 9 | 10 | // Match returns true the current filter matches the given data 11 | func (f *Process_Node_Filter_Condition) Match(data *types.Value) (bool, error) { 12 | switch f.Predicate { 13 | case Process_Node_Filter_Condition_EQ: 14 | return data.Equal(f.Value), nil 15 | case Process_Node_Filter_Condition_GT, 16 | Process_Node_Filter_Condition_GTE, 17 | Process_Node_Filter_Condition_LT, 18 | Process_Node_Filter_Condition_LTE: 19 | n1, ok1 := data.Kind.(*types.Value_NumberValue) 20 | n2, ok2 := f.Value.Kind.(*types.Value_NumberValue) 21 | if !ok1 || !ok2 { 22 | return false, errors.New("predicates GT, GTE, LT, and LTE are only compatible with type Number") 23 | } 24 | switch f.Predicate { 25 | case Process_Node_Filter_Condition_GT: 26 | return n1.NumberValue > n2.NumberValue, nil 27 | case Process_Node_Filter_Condition_GTE: 28 | return n1.NumberValue >= n2.NumberValue, nil 29 | case Process_Node_Filter_Condition_LT: 30 | return n1.NumberValue < n2.NumberValue, nil 31 | case Process_Node_Filter_Condition_LTE: 32 | return n1.NumberValue <= n2.NumberValue, nil 33 | } 34 | case Process_Node_Filter_Condition_CONTAINS: 35 | switch dataTyped := data.Kind.(type) { 36 | case *types.Value_ListValue: 37 | for _, value := range dataTyped.ListValue.Values { 38 | if value.Equal(f.Value) { 39 | return true, nil 40 | } 41 | } 42 | return false, nil 43 | case *types.Value_StringValue: 44 | filter, ok := f.Value.Kind.(*types.Value_StringValue) 45 | if !ok { 46 | return false, errors.New("predicates CONTAINS on data of type String is only compatible with value of type String") 47 | } 48 | return strings.Contains(dataTyped.StringValue, filter.StringValue), nil 49 | default: 50 | return false, errors.New("predicate CONTAINS is only compatible on data of type List or String") 51 | } 52 | } 53 | return false, errors.New("predicates type is unknown") 54 | } 55 | -------------------------------------------------------------------------------- /process/node.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | // NodeType are the string constant corresponding to each type of node. 4 | const ( 5 | NodeTypeUnknown = "unknown" 6 | NodeTypeResult = "result" 7 | NodeTypeEvent = "event" 8 | NodeTypeTask = "task" 9 | NodeTypeMap = "map" 10 | NodeTypeFilter = "filter" 11 | ) 12 | 13 | // TypeString returns the type of the node in string 14 | func (node *Process_Node) TypeString() string { 15 | switch node.Type.(type) { 16 | case *Process_Node_Result_: 17 | return NodeTypeResult 18 | case *Process_Node_Event_: 19 | return NodeTypeEvent 20 | case *Process_Node_Task_: 21 | return NodeTypeTask 22 | case *Process_Node_Map_: 23 | return NodeTypeMap 24 | case *Process_Node_Filter_: 25 | return NodeTypeFilter 26 | default: 27 | return NodeTypeUnknown 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /process/process.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/mesg-foundation/engine/ext/xvalidator" 8 | "github.com/mesg-foundation/engine/hash" 9 | "github.com/mesg-foundation/engine/protobuf/types" 10 | "github.com/tendermint/tendermint/crypto" 11 | ) 12 | 13 | // New returns a new process and validate it. 14 | func New(name string, nodes []*Process_Node, edges []*Process_Edge, paymentAddress sdk.AccAddress) (*Process, error) { 15 | p := &Process{ 16 | Name: name, 17 | Nodes: nodes, 18 | Edges: edges, 19 | } 20 | p.Hash = hash.Dump(p) 21 | p.Address = sdk.AccAddress(crypto.AddressHash(p.Hash)) 22 | p.PaymentAddress = paymentAddress 23 | return p, p.Validate() 24 | } 25 | 26 | // Validate returns an error if the process is invalid for whatever reason 27 | func (w *Process) Validate() error { 28 | if err := xvalidator.Struct(w); err != nil { 29 | return err 30 | } 31 | if err := w.validate(); err != nil { 32 | return err 33 | } 34 | if _, err := w.Trigger(); err != nil { 35 | return err 36 | } 37 | for _, node := range w.Nodes { 38 | switch n := node.GetType().(type) { 39 | case *Process_Node_Map_: 40 | for _, output := range n.Map.Outputs { 41 | if ref := output.GetRef(); ref != nil { 42 | if _, err := w.FindNode(ref.NodeKey); err != nil { 43 | return err 44 | } 45 | } 46 | } 47 | case *Process_Node_Filter_: 48 | for _, condition := range n.Filter.Conditions { 49 | switch condition.Predicate { 50 | case Process_Node_Filter_Condition_GT, 51 | Process_Node_Filter_Condition_GTE, 52 | Process_Node_Filter_Condition_LT, 53 | Process_Node_Filter_Condition_LTE: 54 | if _, ok := condition.Value.Kind.(*types.Value_NumberValue); !ok { 55 | return fmt.Errorf("filter with condition GT, GTE, LT or LTE only works with value of type Number") 56 | } 57 | } 58 | if _, err := w.FindNode(condition.Ref.NodeKey); err != nil { 59 | return err 60 | } 61 | } 62 | } 63 | } 64 | if err := w.shouldBeDirectedTree(); err != nil { 65 | return err 66 | } 67 | return nil 68 | } 69 | 70 | // Trigger returns the trigger of the process 71 | func (w *Process) Trigger() (*Process_Node, error) { 72 | triggers := w.FindNodes(func(n *Process_Node) bool { 73 | return n.GetResult() != nil || n.GetEvent() != nil 74 | }) 75 | if len(triggers) != 1 { 76 | return nil, fmt.Errorf("should contain exactly one trigger (result or event)") 77 | } 78 | return triggers[0], nil 79 | } 80 | -------------------------------------------------------------------------------- /process/ref.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/mesg-foundation/engine/protobuf/types" 7 | ) 8 | 9 | // Resolve returns the value specified in the reference. 10 | func (path *Process_Node_Reference_Path) Resolve(data *types.Struct) (*types.Value, error) { 11 | if path == nil { 12 | return &types.Value{Kind: &types.Value_StructValue{StructValue: data}}, nil 13 | } 14 | 15 | var v *types.Value 16 | key, ok := path.Selector.(*Process_Node_Reference_Path_Key) 17 | if !ok { 18 | return nil, fmt.Errorf("first selector in the path must be a key") 19 | } 20 | 21 | v, ok = data.Fields[key.Key] 22 | if !ok { 23 | return nil, fmt.Errorf("key %s not found", key.Key) 24 | } 25 | 26 | for p := path.Path; p != nil; p = p.Path { 27 | switch s := p.Selector.(type) { 28 | case *Process_Node_Reference_Path_Key: 29 | str, ok := v.GetKind().(*types.Value_StructValue) 30 | if !ok { 31 | return nil, fmt.Errorf("can't get key from non-struct value") 32 | } 33 | if str.StructValue.GetFields() == nil { 34 | return nil, fmt.Errorf("can't get key from nil-struct") 35 | } 36 | v, ok = str.StructValue.Fields[s.Key] 37 | if !ok { 38 | return nil, fmt.Errorf("key %s not found", s.Key) 39 | } 40 | case *Process_Node_Reference_Path_Index: 41 | list, ok := v.GetKind().(*types.Value_ListValue) 42 | if !ok { 43 | return nil, fmt.Errorf("can't get index from non-list value") 44 | } 45 | 46 | if len(list.ListValue.GetValues()) <= int(s.Index) { 47 | return nil, fmt.Errorf("index %d out of range", s.Index) 48 | } 49 | v = list.ListValue.Values[s.Index] 50 | default: 51 | return nil, fmt.Errorf("unknown selector type %T", v) 52 | } 53 | } 54 | 55 | return v, nil 56 | } 57 | -------------------------------------------------------------------------------- /protobuf/acknowledgement/stream.go: -------------------------------------------------------------------------------- 1 | package acknowledgement 2 | 3 | import ( 4 | fmt "fmt" 5 | 6 | grpc "google.golang.org/grpc" 7 | "google.golang.org/grpc/metadata" 8 | ) 9 | 10 | const ( 11 | statusKey = "status" 12 | statusReady = "ready" 13 | ) 14 | 15 | // WaitForStreamToBeReady waits until the server publish a header with status ready on the stream. 16 | func WaitForStreamToBeReady(stream grpc.ClientStream) error { 17 | // wait for header. 18 | header, err := stream.Header() 19 | if err != nil { 20 | return err 21 | } 22 | // header received. check status. 23 | statuses := header.Get(statusKey) 24 | statusesLen := len(statuses) 25 | if statusesLen == 0 { 26 | return nil // Ignore headers with no status key 27 | } 28 | lastStatus := statuses[statusesLen-1] 29 | if lastStatus != statusReady { 30 | return fmt.Errorf("stream header status is different than ready. Got %q", lastStatus) 31 | } 32 | return nil 33 | } 34 | 35 | // SetStreamReady send an header on the stream to notify the server is ready. 36 | func SetStreamReady(stream grpc.ServerStream) error { 37 | return stream.SendHeader(metadata.Pairs(statusKey, statusReady)) 38 | } 39 | -------------------------------------------------------------------------------- /protobuf/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // RegisterCodec register struct type in cdc. 8 | func RegisterCodec(cdc *codec.Codec) { 9 | cdc.RegisterInterface((*isValue_Kind)(nil), nil) 10 | cdc.RegisterConcrete(&Value_NullValue{}, "mesg.types.Value_NullValue", nil) 11 | cdc.RegisterConcrete(&Value_NumberValue{}, "mesg.types.Value_NumberValue", nil) 12 | cdc.RegisterConcrete(&Value_StringValue{}, "mesg.types.Value_StringValue", nil) 13 | cdc.RegisterConcrete(&Value_BoolValue{}, "mesg.types.Value_BoolValue", nil) 14 | cdc.RegisterConcrete(&Value_ListValue{}, "mesg.types.Value_ListValue", nil) 15 | cdc.RegisterConcrete(&Value_StructValue{}, "mesg.types.Value_StructValue", nil) 16 | } 17 | -------------------------------------------------------------------------------- /protobuf/types/event.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | import "protobuf/types/struct.proto"; 5 | 6 | package mesg.types; 7 | option go_package = "github.com/mesg-foundation/engine/event"; 8 | 9 | option (gogoproto.goproto_getters_all) = false; 10 | 11 | // Event represents a single event run in engine. 12 | message Event { 13 | // Hash is a unique hash to identify event. 14 | bytes hash = 1 [ 15 | (gogoproto.moretags) = 'hash:"-" validate:"required,hash"', 16 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 17 | ]; 18 | 19 | // instanceHash is hash of instance that can proceed an execution. 20 | bytes instanceHash = 2 [ 21 | (gogoproto.moretags) = 'hash:"name:2" validate:"required,hash"', 22 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 23 | ]; 24 | 25 | // key is the key of the event. 26 | string key = 3 [ 27 | (gogoproto.moretags) = 'hash:"name:3" validate:"required,printascii"' 28 | ]; 29 | 30 | // data is the data for the event. 31 | mesg.protobuf.Struct data = 4 [ 32 | (gogoproto.moretags) = 'hash:"name:4"' 33 | ]; 34 | } 35 | -------------------------------------------------------------------------------- /protobuf/types/instance.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | 5 | package mesg.types; 6 | option go_package = "github.com/mesg-foundation/engine/instance"; 7 | 8 | option (gogoproto.goproto_getters_all) = false; 9 | option (gogoproto.equal_all) = true; 10 | 11 | // Instance represents service's instance. 12 | message Instance { 13 | bytes hash = 1 [ 14 | (gogoproto.moretags) = 'hash:"-" validate:"required,hash"', 15 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 16 | ]; 17 | 18 | bytes serviceHash = 2 [ 19 | (gogoproto.moretags) = 'hash:"name:2" validate:"required,hash"', 20 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 21 | ]; 22 | 23 | bytes envHash = 3 [ 24 | (gogoproto.moretags) = 'hash:"name:3" validate:"omitempty,hash"', 25 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 26 | ]; 27 | } 28 | -------------------------------------------------------------------------------- /protobuf/types/ownership.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | 5 | package mesg.types; 6 | option go_package = "github.com/mesg-foundation/engine/ownership"; 7 | 8 | option (gogoproto.goproto_getters_all) = false; 9 | option (gogoproto.equal_all) = true; 10 | 11 | 12 | // Ownership is a ownership relation between one owner and a resource. 13 | message Ownership { 14 | 15 | // Service's hash. 16 | bytes hash = 1 [ 17 | (gogoproto.moretags) = 'hash:"-" validate:"required,hash"', 18 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 19 | ]; 20 | 21 | // The owner of the resource. 22 | // TODO: to transform to accAddress 23 | string owner = 2 [ 24 | (gogoproto.moretags) = 'hash:"name:2" validate:"required"' 25 | ]; 26 | 27 | // Resource's hash. 28 | bytes resourceHash = 3 [ 29 | (gogoproto.moretags) = 'hash:"name:3" validate:"required,hash"', 30 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 31 | ]; 32 | 33 | enum Resource { 34 | None = 0; 35 | Service = 1; 36 | Process = 2; 37 | Runner = 3; 38 | } 39 | 40 | // Resource's type. 41 | Resource resource = 4 [ 42 | (gogoproto.moretags) = 'validate:"required"' 43 | ]; 44 | 45 | // The address of the resource. 46 | bytes resourceAddress = 5 [ 47 | (gogoproto.moretags) = 'hash:"-" validate:"required,accaddress"', 48 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 49 | ]; 50 | } 51 | -------------------------------------------------------------------------------- /protobuf/types/runner.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | 5 | package mesg.types; 6 | option go_package = "github.com/mesg-foundation/engine/runner"; 7 | 8 | option (gogoproto.goproto_getters_all) = false; 9 | option (gogoproto.equal_all) = true; 10 | 11 | // Runner represents one node service's instance. 12 | message Runner { 13 | // Runner's hash 14 | bytes hash = 1 [ 15 | (gogoproto.moretags) = 'hash:"-" validate:"required,hash"', 16 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 17 | ]; 18 | 19 | // owner of the engine of this runner 20 | string owner = 2 [ 21 | (gogoproto.moretags) = 'hash:"name:2" validate:"required"' 22 | ]; 23 | 24 | // instanceHash is hash of the instance that runner will handle 25 | bytes instanceHash = 3 [ 26 | (gogoproto.moretags) = 'hash:"name:3" validate:"required,hash"', 27 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 28 | ]; 29 | 30 | // The address of the runner. 31 | bytes address = 4 [ 32 | (gogoproto.moretags) = 'hash:"-" validate:"required,accaddress"', 33 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 34 | ]; 35 | } 36 | -------------------------------------------------------------------------------- /protobuf/types/struct.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "sort" 5 | ) 6 | 7 | // KeyValue is a simple key/value representation of one field of a Struct. 8 | type KeyValue struct { 9 | Key string 10 | Value *Value 11 | } 12 | 13 | // MarshalAmino transforms the Struct to an array of key/value. 14 | func (m Struct) MarshalAmino() ([]KeyValue, error) { 15 | p := make([]KeyValue, len(m.Fields)) 16 | fieldKeys := make([]string, len(m.Fields)) 17 | i := 0 18 | for key := range m.Fields { 19 | fieldKeys[i] = key 20 | i++ 21 | } 22 | sort.Stable(sort.StringSlice(fieldKeys)) 23 | for i, key := range fieldKeys { 24 | p[i] = KeyValue{ 25 | Key: key, 26 | Value: m.Fields[key], 27 | } 28 | } 29 | return p, nil 30 | } 31 | 32 | // UnmarshalAmino transforms the key/value array to a Struct. 33 | func (m *Struct) UnmarshalAmino(keyValues []KeyValue) error { 34 | m.Fields = make(map[string]*Value, len(keyValues)) 35 | for _, p := range keyValues { 36 | m.Fields[p.Key] = p.Value 37 | } 38 | return nil 39 | } 40 | -------------------------------------------------------------------------------- /runner/runner.go: -------------------------------------------------------------------------------- 1 | package runner 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/ext/xvalidator" 6 | "github.com/mesg-foundation/engine/hash" 7 | "github.com/tendermint/tendermint/crypto" 8 | ) 9 | 10 | // New returns a new execution. 11 | func New(owner string, instanceHash hash.Hash) (*Runner, error) { 12 | run := &Runner{ 13 | Owner: owner, 14 | InstanceHash: instanceHash, 15 | } 16 | run.Hash = hash.Dump(run) 17 | run.Address = sdk.AccAddress(crypto.AddressHash(run.Hash)) 18 | return run, xvalidator.Struct(run) 19 | } 20 | -------------------------------------------------------------------------------- /scripts/build-proto.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # generate modules' msg 4 | protoc --gogo_out=paths=source_relative:. x/service/internal/types/msg.proto 5 | protoc --gogo_out=paths=source_relative:. x/process/internal/types/msg.proto 6 | protoc --gogo_out=paths=source_relative:. x/runner/internal/types/msg.proto 7 | protoc --gogo_out=paths=source_relative:. x/execution/internal/types/msg.proto 8 | protoc --gogo_out=paths=source_relative:. x/ownership/internal/types/msg.proto 9 | protoc --gogo_out=paths=source_relative:. x/credit/internal/types/msg.proto 10 | 11 | # generate gRPC api 12 | protoc --gogo_out=paths=source_relative,plugins=grpc:. server/grpc/runner/runner.proto 13 | protoc --gogo_out=paths=source_relative,plugins=grpc:. server/grpc/orchestrator/execution.proto 14 | protoc --gogo_out=paths=source_relative,plugins=grpc:. server/grpc/orchestrator/runner.proto 15 | protoc --gogo_out=paths=source_relative,plugins=grpc:. server/grpc/orchestrator/event.proto 16 | 17 | TYPES_PATH=protobuf/types 18 | 19 | # generate type 20 | for file in "${TYPES_PATH}"/{event,execution,instance,service,process,ownership,runner}.proto 21 | do 22 | file=$(basename ${file}) 23 | dir="${file%.*}" 24 | protoc --gogo_out=paths=source_relative:"${dir}" --proto_path . --proto_path "${TYPES_PATH}" "${file}" 25 | done 26 | 27 | # generate google type 28 | protoc --gogo_out=paths=source_relative:. protobuf/types/struct.proto 29 | -------------------------------------------------------------------------------- /scripts/changelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -z "$1" ] && echo "milestone required" && exit 4 | 5 | MILESTONE="$1" 6 | 7 | LABELS=("breaking change" "release:add" "release:change" "release:fix" "release:remove" "dependencies") 8 | CATEGORIES=("Breaking Changes" "Added" "Changed" "Fixed" "Removed" "Dependencies") 9 | 10 | PR=$(hub pr list -s merged -f "%Mt %L|- ([%i](%U)) %t.%n" --sort-ascending | grep $MILESTONE) 11 | 12 | printf "## [$MILESTONE](https://github.com/mesg-foundation/engine/releases/tag/$MILESTONE)\n\n" 13 | 14 | for i in "${!LABELS[@]}"; do 15 | LABEL=${LABELS[$i]} 16 | CATEGORY=${CATEGORIES[$i]} 17 | printf "#### $CATEGORY\n\n" 18 | echo "$PR" | grep "$LABEL" | cut -d'|' -f2 19 | printf "\n" 20 | done 21 | -------------------------------------------------------------------------------- /scripts/dev-starter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # turn on bash's job control 4 | set -m 5 | 6 | # start daemon 7 | mesg-daemon start & 8 | daemon=$! 9 | 10 | # function that stop child processes 11 | function stop { 12 | echo "stopping daemon" 13 | kill $daemon 14 | wait $daemon 15 | exit 0 16 | } 17 | 18 | # trap both sigint (ctrl+c) and sigterm (OS ask process to be stopped) 19 | trap stop SIGINT 20 | trap stop SIGTERM 21 | 22 | # wait 5 sec for the daemon to start rpc server 23 | sleep 5 & 24 | wait $! 25 | 26 | # start lcd 27 | echo "starting lcd" 28 | mesg-cli rest-server --laddr tcp://0.0.0.0:1317 & 29 | lcd=$! 30 | 31 | # start orchestrator 32 | echo "starting orchestrator" 33 | mesg-cli orchestrator start & 34 | orchestrator=$! 35 | 36 | # this variable is used to control the monitoring of the child process 37 | monitoring=true 38 | 39 | # function that stop child processes 40 | function stop { 41 | monitoring=false 42 | echo "stopping all child processes" 43 | kill $daemon $lcd $orchestrator 44 | wait $daemon $lcd $orchestrator 45 | } 46 | 47 | # trap both sigint (ctrl+c) and sigterm (OS ask process to be stopped) 48 | trap stop SIGINT 49 | trap stop SIGTERM 50 | 51 | # start the monitoring loop 52 | while $monitoring 53 | do 54 | # check if all sub processes are running correctly 55 | if [[ -n "$(ps -p $daemon -o pid=)" ]] && [[ -n "$(ps -p $lcd -o pid=)" ]] && [[ -n "$(ps -p $orchestrator -o pid=)" ]]; then 56 | sleep 2 & 57 | wait $! 58 | else 59 | # if one child process is not running, stopping all of them and exit with error code 1 60 | echo "one child process is not running" 61 | stop 62 | exit 1 63 | fi 64 | done 65 | -------------------------------------------------------------------------------- /scripts/dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | ENGINE_NAME="engine" 6 | NETWORK_NAME="engine" 7 | 8 | if [[ -z "$1" ]]; then 9 | echo -e "arg version is missing, run:\n" 10 | echo "$0 vX.X.X" 11 | exit 1 12 | fi 13 | 14 | monitoring=false 15 | if [[ "$2" == "monitoring" ]]; then 16 | monitoring=true 17 | fi 18 | 19 | function onexit { 20 | docker stop $ENGINE_NAME 21 | 22 | if $monitoring; then 23 | docker stop engine-grafana engine-prometheus 24 | fi 25 | 26 | docker network remove $NETWORK_NAME 27 | } 28 | 29 | trap onexit EXIT 30 | 31 | if [[ -z $(docker network list -f name="$NETWORK_NAME" -q) ]]; then 32 | docker network create $NETWORK_NAME 33 | fi 34 | 35 | if $monitoring; then 36 | echo "start monitoring" 37 | docker run \ 38 | -d \ 39 | --rm \ 40 | --name=engine-grafana \ 41 | -p 3001:3000 \ 42 | --network $NETWORK_NAME \ 43 | --mount type=bind,source=$(pwd)/scripts/monitoring/datasource.yml,destination=/etc/grafana/provisioning/datasources/datasource.yml \ 44 | --mount type=bind,source=$(pwd)/scripts/monitoring/dashboard.yml,destination=/etc/grafana/provisioning/dashboards/dashboard.yml \ 45 | --mount type=bind,source=$(pwd)/scripts/monitoring/dashboards,destination=/var/lib/grafana/dashboards \ 46 | grafana/grafana 47 | 48 | docker run \ 49 | -d \ 50 | --rm \ 51 | --name=engine-prometheus \ 52 | -p 9090:9090 \ 53 | --network $NETWORK_NAME \ 54 | --mount type=bind,source=$(pwd)/scripts/monitoring/prometheus.yml,destination=/etc/prometheus/prometheus.yml \ 55 | prom/prometheus 56 | fi 57 | 58 | docker run \ 59 | -d \ 60 | --rm \ 61 | --name $ENGINE_NAME \ 62 | -p 1317:1317 \ 63 | -p 50052:50052 \ 64 | -p 26657:26657 \ 65 | --network $NETWORK_NAME \ 66 | --volume engine:/root/ \ 67 | mesg/engine:$1-dev 68 | 69 | docker logs --tail 1000 --follow $ENGINE_NAME 70 | -------------------------------------------------------------------------------- /scripts/monitoring/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | # an unique provider name 5 | - name: 'dashboard' 6 | # org id. will default to orgId 1 if not specified 7 | orgId: 1 8 | # name of the dashboard folder. Required 9 | folder: '' 10 | # folder UID. will be automatically generated if not specified 11 | folderUid: '' 12 | # provider type. Required 13 | type: file 14 | # disable dashboard deletion 15 | disableDeletion: false 16 | # enable dashboard editing 17 | editable: true 18 | # how often Grafana will scan for changed dashboards 19 | updateIntervalSeconds: 10 20 | # allow updating provisioned dashboards from the UI 21 | allowUiUpdates: false 22 | options: 23 | # path to dashboard files on disk. Required 24 | path: /var/lib/grafana/dashboards -------------------------------------------------------------------------------- /scripts/monitoring/datasource.yml: -------------------------------------------------------------------------------- 1 | # grafana datasource 2 | 3 | # config file version 4 | apiVersion: 1 5 | 6 | # list of datasources that should be deleted from the database 7 | deleteDatasources: 8 | - name: Prometheus 9 | orgId: 1 10 | 11 | # list of datasources to insert/update depending 12 | # whats available in the database 13 | datasources: 14 | # name of the datasource. Required 15 | - name: Prometheus 16 | # datasource type. Required 17 | type: prometheus 18 | # access mode. direct or proxy. Required 19 | access: proxy 20 | # org id. will default to orgId 1 if not specified 21 | orgId: 1 22 | # url 23 | url: http://engine-prometheus:9090 24 | # database password, if used 25 | password: 26 | # database user, if used 27 | user: 28 | # database name, if used 29 | database: 30 | # enable/disable basic auth 31 | basicAuth: true 32 | # basic auth username 33 | basicAuthUser: admin 34 | # basic auth password 35 | basicAuthPassword: foobar 36 | # enable/disable with credentials headers 37 | withCredentials: 38 | # mark as default datasource. Max one per org 39 | isDefault: true 40 | # fields that will be converted to json and stored in json_data 41 | jsonData: 42 | graphiteVersion: "1.1" 43 | tlsAuth: false 44 | tlsAuthWithCACert: false 45 | # json object of data that will be encrypted. 46 | secureJsonData: 47 | tlsCACert: "..." 48 | tlsClientCert: "..." 49 | tlsClientKey: "..." 50 | version: 1 51 | # allow users to edit datasources from the UI. 52 | editable: true 53 | -------------------------------------------------------------------------------- /scripts/monitoring/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | evaluation_interval: 15s 4 | scrape_configs: 5 | - job_name: 'prometheus' 6 | static_configs: 7 | - targets: ['localhost:9090'] 8 | - job_name: 'testnet' 9 | scrape_interval: 15s 10 | static_configs: 11 | - targets: ['engine:26660'] 12 | labels: 13 | instance: 'engine' 14 | -------------------------------------------------------------------------------- /scripts/run-e2e.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | ENGINE_NAME="engine" 6 | NETWORK_NAME="engine" 7 | 8 | if [[ -z "$1" ]]; then 9 | echo -e "arg version is missing, run:\n" 10 | echo "$0 vX.X.X" 11 | exit 1 12 | fi 13 | 14 | 15 | echo "run non existing test to detect compilation error quickly" 16 | go test -mod=readonly -v -count=1 ./e2e/... -run=__NONE__ 17 | 18 | function onexit { 19 | docker stop $ENGINE_NAME 20 | docker network remove $NETWORK_NAME 21 | } 22 | 23 | trap onexit EXIT 24 | 25 | if [[ -z $(docker network list -f name="$NETWORK_NAME" -q) ]]; then 26 | docker network create $NETWORK_NAME 27 | fi 28 | 29 | docker run \ 30 | -d \ 31 | --rm \ 32 | --name $ENGINE_NAME \ 33 | -p 1317:1317 \ 34 | -p 50052:50052 \ 35 | -p 26657:26657 \ 36 | --network $NETWORK_NAME \ 37 | mesg/engine:$1-dev 38 | 39 | echo "waiting lcd server to start" 40 | while true; do 41 | printf '.' 42 | block=$(curl --silent http://localhost:1317/node_info | jq .node_info.protocol_version.block) 43 | if [[ -n $block ]]; then 44 | break 45 | fi 46 | sleep 1 47 | done 48 | 49 | echo "starting tests" 50 | go test -failfast -mod=readonly -v -count=1 ./e2e/... 51 | -------------------------------------------------------------------------------- /server/grpc/logger.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | tmlog "github.com/tendermint/tendermint/libs/log" 5 | ) 6 | 7 | func newTmLogger(logger tmlog.Logger, msg string) *tmLogger { 8 | return &tmLogger{ 9 | Logger: logger, 10 | msg: msg, 11 | } 12 | } 13 | 14 | type tmLogger struct { 15 | tmlog.Logger 16 | msg string 17 | } 18 | 19 | func (l tmLogger) Log(keyvals ...interface{}) error { 20 | l.Info(l.msg, keyvals...) 21 | return nil 22 | } 23 | -------------------------------------------------------------------------------- /server/grpc/orchestrator/authorizer.go: -------------------------------------------------------------------------------- 1 | package orchestrator 2 | 3 | import ( 4 | "context" 5 | "encoding/base64" 6 | "fmt" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | "github.com/tendermint/tendermint/crypto" 11 | "google.golang.org/grpc/metadata" 12 | ) 13 | 14 | // RequestSignature is the name of the key to use in the gRPC metadata to set the request signature. 15 | const RequestSignature = "mesg_request_signature" 16 | 17 | // Authorizer is the type to aggregate all Admin APIs. 18 | type Authorizer struct { 19 | cdc *codec.Codec 20 | authorizedPubKeys []crypto.PubKey 21 | } 22 | 23 | // NewAuthorizer creates a new Authorizer. 24 | func NewAuthorizer(cdc *codec.Codec, authorizedPubKeys []string) (*Authorizer, error) { 25 | // decode public keys 26 | pks := make([]crypto.PubKey, 0) 27 | for _, pkS := range authorizedPubKeys { 28 | pk, err := sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, pkS) 29 | if err != nil { 30 | return nil, err 31 | } 32 | pks = append(pks, pk) 33 | } 34 | 35 | return &Authorizer{ 36 | cdc: cdc, 37 | authorizedPubKeys: pks, 38 | }, nil 39 | } 40 | 41 | // IsAuthorized checks the context for a signature signed by one of the authorizedPubKeys. 42 | func (a *Authorizer) IsAuthorized(ctx context.Context, payload interface{}) error { 43 | md, ok := metadata.FromIncomingContext(ctx) 44 | if !ok { 45 | return fmt.Errorf("signature not found in metadata, make sure to set it using the key %q", RequestSignature) 46 | } 47 | if len(md[RequestSignature]) == 0 { 48 | return fmt.Errorf("signature not found in metadata, make sure to set it using the key %q", RequestSignature) 49 | } 50 | signature := md[RequestSignature][0] 51 | signatureBytes, err := base64.StdEncoding.DecodeString(signature) 52 | if err != nil { 53 | return err 54 | } 55 | encodedValue, err := a.cdc.MarshalJSON(payload) 56 | if err != nil { 57 | return err 58 | } 59 | encodedValueSorted, err := sdk.SortJSON(encodedValue) 60 | if err != nil { 61 | return err 62 | } 63 | isAuthorized := false 64 | for _, authorizedPubKey := range a.authorizedPubKeys { 65 | if authorizedPubKey.VerifyBytes(encodedValueSorted, signatureBytes) { 66 | isAuthorized = true 67 | break 68 | } 69 | } 70 | if !isAuthorized { 71 | return fmt.Errorf("verification of the signature failed") 72 | } 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /server/grpc/orchestrator/event.go: -------------------------------------------------------------------------------- 1 | package orchestrator 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/event" 5 | "github.com/mesg-foundation/engine/event/publisher" 6 | "github.com/mesg-foundation/engine/protobuf/acknowledgement" 7 | ) 8 | 9 | type eventServer struct { 10 | eventPublisher *publisher.EventPublisher 11 | auth *Authorizer 12 | } 13 | 14 | // NewEventServer creates a new Event Server. 15 | func NewEventServer(eventPublisher *publisher.EventPublisher, auth *Authorizer) EventServer { 16 | return &eventServer{ 17 | eventPublisher: eventPublisher, 18 | auth: auth, 19 | } 20 | } 21 | 22 | // Stream returns stream of events. 23 | func (s *eventServer) Stream(req *EventStreamRequest, stream Event_StreamServer) error { 24 | // check authorization 25 | if err := s.auth.IsAuthorized(stream.Context(), req); err != nil { 26 | return err 27 | } 28 | 29 | var f *event.Filter 30 | if req.Filter != nil { 31 | f = &event.Filter{ 32 | Hash: req.Filter.Hash, 33 | InstanceHash: req.Filter.InstanceHash, 34 | Key: req.Filter.Key, 35 | } 36 | } 37 | eventStream := s.eventPublisher.GetStream(f) 38 | defer eventStream.Close() 39 | 40 | // send header to notify client that the stream is ready. 41 | if err := acknowledgement.SetStreamReady(stream); err != nil { 42 | return err 43 | } 44 | 45 | for { 46 | select { 47 | case event := <-eventStream.C: 48 | if err := stream.Send(event); err != nil { 49 | return err 50 | } 51 | case <-stream.Context().Done(): 52 | return stream.Context().Err() 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /server/grpc/orchestrator/event.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | import "protobuf/types/event.proto"; 5 | 6 | package mesg.grpc.orchestrator; 7 | option go_package = "github.com/mesg-foundation/engine/service/grpc/orchestrator"; 8 | 9 | // This is the Event API to interact with the Orchestrator. 10 | // This API requires all requests to be signed for authentication. The signature should be passed in the request's metadata using the key `mesg_request_signature` and base64 encoded. 11 | service Event { 12 | // Stream returns a stream of events that satisfy criteria specified. 13 | rpc Stream(EventStreamRequest) returns (stream types.Event) {} 14 | } 15 | 16 | // Stream returns a stream of events that satisfy specified filter. 17 | message EventStreamRequest { 18 | // Filter contains filtering criteria. 19 | message Filter { 20 | // hash to filter events. 21 | bytes hash = 1 [ 22 | (gogoproto.moretags) = 'validate:"omitempty,hash"', 23 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 24 | ]; 25 | 26 | // instance's hash to filter events. 27 | bytes instanceHash = 2 [ 28 | (gogoproto.moretags) = 'validate:"omitempty,hash"', 29 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 30 | ]; 31 | 32 | // key is the key of the event. 33 | string key = 3 [ 34 | (gogoproto.moretags) = 'validate:"printascii"' 35 | ]; 36 | } 37 | 38 | // Filter used to filter a stream of events. 39 | Filter filter = 1; 40 | } 41 | -------------------------------------------------------------------------------- /server/grpc/orchestrator/runner.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | 5 | package mesg.grpc.orchestrator; 6 | option go_package = "github.com/mesg-foundation/engine/service/grpc/orchestrator"; 7 | 8 | // This is the Runner API to interact with the Orchestrator. 9 | // This API requires all requests to be signed for authentication. The signature should be passed in the request's metadata using the key `mesg_request_signature` and base64 encoded. 10 | service Runner { 11 | // Register registers a new runner to the Engine. 12 | // This endpoint should only be called when the runner is ready to receive execution and emit events. 13 | // This endpoint returns a credential token that must be use to reach the Runner APIs. 14 | rpc Register(RunnerRegisterRequest) returns (RunnerRegisterResponse) {} 15 | 16 | // Delete a runner from the blockchain. 17 | rpc Delete(RunnerDeleteRequest) returns (RunnerDeleteResponse) {} 18 | } 19 | 20 | // RunnerRegisterRequest is the request of the endpoint Register. 21 | message RunnerRegisterRequest { 22 | // Service's hash to start the runner with. 23 | bytes serviceHash = 1 [ 24 | (gogoproto.moretags) = 'validate:"required,hash"', 25 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 26 | ]; 27 | 28 | // Hash of the customized environmental variables (not the ones in the service configuration). 29 | bytes envHash = 2 [ 30 | (gogoproto.moretags) = 'validate:"omitempty,hash"', 31 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 32 | ]; 33 | } 34 | 35 | // RunnerRegisterResponse is the response of the endpoint Register. 36 | message RunnerRegisterResponse { 37 | // token to use with the other endpoints of this API. 38 | string token = 1; 39 | } 40 | 41 | // RunnerDeleteRequest is the request of the endpoint DeleteRunner. 42 | message RunnerDeleteRequest { 43 | bytes runnerHash = 1 [ 44 | (gogoproto.moretags) = 'validate:"required,hash"', 45 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 46 | ]; 47 | } 48 | 49 | // RunnerDeleteResponse is the response of the endpoint DeleteRunner. 50 | message RunnerDeleteResponse {} 51 | -------------------------------------------------------------------------------- /server/grpc/runner/runner.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | import "protobuf/types/execution.proto"; 5 | import "protobuf/types/struct.proto"; 6 | 7 | package mesg.grpc.runner; 8 | option go_package = "github.com/mesg-foundation/engine/service/grpc/runner"; 9 | 10 | // This is the API the Runners use to interact with the Engine. 11 | service Runner { 12 | // Execution returns a stream of executions that contains the Execution the Runner must execute. 13 | // This request requires the credential token, obtained from the Register endpoint, to be injected in the request's metadata using the key "mesg_credential_token". 14 | rpc Execution(ExecutionRequest) returns (stream types.Execution) {} 15 | 16 | // Result should be used to return the result of an Execution. 17 | // This request requires the credential token, obtained from the Register endpoint, to be injected in the request's metadata using the key "mesg_credential_token". 18 | rpc Result(ResultRequest) returns (ResultResponse) {} 19 | 20 | // Event should be used to emits an event. 21 | // This request requires the credential token, obtained from the Register endpoint, to be injected in the request's metadata using the key "mesg_credential_token". 22 | rpc Event(EventRequest) returns (EventResponse) {} 23 | } 24 | 25 | // ExecutionRequest is the request of the endpoint Execution. 26 | message ExecutionRequest {} 27 | 28 | // EventRequest is the request of the endpoint Result. 29 | message ResultRequest { 30 | // Execution's hash of the executed execution. 31 | bytes executionHash = 1 [ 32 | (gogoproto.moretags) = 'validate:"required,hash"', 33 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 34 | ]; 35 | 36 | // Execution's result. 37 | oneof result { 38 | // outputs of the result. 39 | mesg.protobuf.Struct outputs = 2; 40 | 41 | // error should contain the error occured during the execution. 42 | string error = 3; 43 | } 44 | } 45 | 46 | // ResultResponse is the response of the endpoint Result. 47 | message ResultResponse {} 48 | 49 | 50 | // EventRequest is the request of the endpoint Event. 51 | message EventRequest { 52 | // Event's key 53 | string key = 1 [ 54 | (gogoproto.moretags) = 'validate:"required,printascii"' 55 | ]; 56 | 57 | // Event's data 58 | mesg.protobuf.Struct data = 2; 59 | } 60 | 61 | // EventResponse is the response of the endpoint Event. 62 | message EventResponse {} 63 | -------------------------------------------------------------------------------- /service/service_parameter.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/mesg-foundation/engine/ext/xerrors" 7 | "github.com/mesg-foundation/engine/protobuf/types" 8 | ) 9 | 10 | // validateServiceParameters validates data to see if it matches with parameters schema. 11 | func validateServiceParameters(parameters []*Service_Parameter, data *types.Struct) error { 12 | var errs xerrors.Errors 13 | 14 | for _, p := range parameters { 15 | var value *types.Value 16 | if data != nil && data.Fields != nil { 17 | value = data.Fields[p.Key] 18 | } 19 | if err := p.Validate(value); err != nil { 20 | errs = append(errs, err) 21 | } 22 | } 23 | return errs.ErrorOrNil() 24 | } 25 | 26 | // Validate checks if service parameter hash proper types for arrays and objects. 27 | func (p *Service_Parameter) Validate(value *types.Value) error { 28 | _, isNull := value.GetKind().(*types.Value_NullValue) 29 | if value == nil || isNull { 30 | if p.Optional { 31 | return nil 32 | } 33 | return fmt.Errorf("value of %q is required", p.Key) 34 | } 35 | 36 | if p.Repeated { 37 | array := value.GetListValue() 38 | if array == nil { 39 | return fmt.Errorf("value of %q is not an array", p.Key) 40 | } 41 | 42 | for _, value := range array.Values { 43 | if err := p.validateType(value); err != nil { 44 | return err 45 | } 46 | } 47 | return nil 48 | } 49 | return p.validateType(value) 50 | } 51 | 52 | // validateType checks if value comforts its expected type. 53 | func (p *Service_Parameter) validateType(value *types.Value) error { 54 | switch p.Type { 55 | case "String": 56 | if _, ok := value.GetKind().(*types.Value_StringValue); !ok { 57 | return fmt.Errorf("value of %q is not a string", p.Key) 58 | } 59 | case "Number": 60 | if _, ok := value.GetKind().(*types.Value_NumberValue); !ok { 61 | return fmt.Errorf("value of %q is not a number", p.Key) 62 | } 63 | case "Boolean": 64 | if _, ok := value.GetKind().(*types.Value_BoolValue); !ok { 65 | return fmt.Errorf("value of %q is not a boolean", p.Key) 66 | } 67 | case "Object": 68 | obj, ok := value.GetKind().(*types.Value_StructValue) 69 | if !ok { 70 | return fmt.Errorf("value of %q is not an object", p.Key) 71 | } 72 | return validateServiceParameters(p.Object, obj.StructValue) 73 | case "Any": 74 | return nil 75 | default: 76 | return fmt.Errorf("value of %q has an invalid type ", p.Key) 77 | } 78 | 79 | return nil 80 | } 81 | -------------------------------------------------------------------------------- /service/service_test.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/mesg-foundation/engine/protobuf/types" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestRequire(t *testing.T) { 11 | sp := []*Service_Parameter{ 12 | { 13 | Key: "key", 14 | Type: "Number", 15 | Optional: true, 16 | }, 17 | } 18 | 19 | invalid := &types.Struct{ 20 | Fields: map[string]*types.Value{ 21 | "key": { 22 | Kind: &types.Value_StringValue{}, 23 | }, 24 | }, 25 | } 26 | 27 | s := &Service{ 28 | Events: []*Service_Event{ 29 | { 30 | Key: "event", 31 | Data: sp, 32 | }, 33 | }, 34 | Tasks: []*Service_Task{ 35 | { 36 | Key: "task", 37 | Inputs: sp, 38 | Outputs: sp, 39 | }, 40 | }, 41 | } 42 | 43 | t.Run("RequireTaskInputs", func(t *testing.T) { 44 | require.NoError(t, s.RequireTaskInputs("task", nil)) 45 | require.Error(t, s.RequireTaskInputs("task", invalid)) 46 | require.Error(t, s.RequireTaskInputs("-", nil)) 47 | }) 48 | 49 | t.Run("RequireTaskOutputs", func(t *testing.T) { 50 | require.NoError(t, s.RequireTaskOutputs("task", nil)) 51 | require.Error(t, s.RequireTaskOutputs("task", invalid)) 52 | require.Error(t, s.RequireTaskOutputs("-", nil)) 53 | }) 54 | 55 | t.Run("RequireEventData", func(t *testing.T) { 56 | require.NoError(t, s.RequireEventData("event", nil)) 57 | require.Error(t, s.RequireEventData("event", invalid)) 58 | require.Error(t, s.RequireEventData("-", nil)) 59 | }) 60 | } 61 | -------------------------------------------------------------------------------- /x/credit/abci.go: -------------------------------------------------------------------------------- 1 | package credit 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // BeginBlocker check for infraction evidence or downtime of validators 9 | // on every begin block 10 | func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {} 11 | 12 | // EndBlocker called every block, process inflation, update validator set. 13 | func EndBlocker(ctx sdk.Context, k Keeper) {} 14 | -------------------------------------------------------------------------------- /x/credit/alias.go: -------------------------------------------------------------------------------- 1 | package credit 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/x/credit/internal/keeper" 5 | "github.com/mesg-foundation/engine/x/credit/internal/types" 6 | ) 7 | 8 | // const aliases 9 | const ( 10 | ModuleName = types.ModuleName 11 | RouterKey = types.RouterKey 12 | StoreKey = types.StoreKey 13 | DefaultParamspace = types.DefaultParamspace 14 | QuerierRoute = types.QuerierRoute 15 | ) 16 | 17 | // functions and variable aliases 18 | var ( 19 | NewKeeper = keeper.NewKeeper 20 | NewQuerier = keeper.NewQuerier 21 | RegisterCodec = types.RegisterCodec 22 | NewGenesisState = types.NewGenesisState 23 | DefaultGenesisState = types.DefaultGenesisState 24 | ValidateGenesis = types.ValidateGenesis 25 | 26 | ModuleCdc = types.ModuleCdc 27 | QueryGet = types.QueryGet 28 | QueryParameters = types.QueryParameters 29 | 30 | EventType = types.EventType 31 | AttributeActionAdded = types.AttributeActionAdded 32 | AttributeActionSubtracted = types.AttributeActionSubtracted 33 | ) 34 | 35 | // module types 36 | type ( 37 | Keeper = keeper.Keeper 38 | GenesisState = types.GenesisState 39 | Params = types.Params 40 | 41 | MsgAdd = types.MsgAdd 42 | ) 43 | -------------------------------------------------------------------------------- /x/credit/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/context" 8 | "github.com/cosmos/cosmos-sdk/client/flags" 9 | "github.com/cosmos/cosmos-sdk/codec" 10 | "github.com/mesg-foundation/engine/x/credit/internal/types" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | // GetQueryCmd returns the cli query commands for this module 15 | func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { 16 | // Group credit queries under a subcommand 17 | creditQueryCmd := &cobra.Command{ 18 | Use: types.ModuleName, 19 | Short: fmt.Sprintf("Query commands for the %s module", types.ModuleName), 20 | DisableFlagParsing: true, 21 | SuggestionsMinimumDistance: 2, 22 | RunE: client.ValidateCmd, 23 | } 24 | 25 | creditQueryCmd.AddCommand( 26 | flags.GetCommands( 27 | GetCmdGet(queryRoute, cdc), 28 | GetCmdQueryParams(queryRoute, cdc), 29 | )..., 30 | ) 31 | 32 | return creditQueryCmd 33 | } 34 | 35 | // GetCmdGet implements the get query command. 36 | func GetCmdGet(queryRoute string, cdc *codec.Codec) *cobra.Command { 37 | return &cobra.Command{ 38 | Use: "get [address]", 39 | Short: "Fetch the number of credits of an address", 40 | Args: cobra.ExactArgs(1), 41 | RunE: func(cmd *cobra.Command, args []string) error { 42 | cliCtx := context.NewCLIContext().WithCodec(cdc) 43 | res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", queryRoute, types.QueryGet, args[0]), nil) 44 | if err != nil { 45 | fmt.Printf("could not get credit\n%s\n", err.Error()) 46 | return nil 47 | } 48 | 49 | var out string 50 | cdc.MustUnmarshalJSON(res, &out) 51 | return cliCtx.PrintOutput(out) 52 | }, 53 | } 54 | } 55 | 56 | // GetCmdQueryParams implements the params query command. 57 | func GetCmdQueryParams(queryRoute string, cdc *codec.Codec) *cobra.Command { 58 | return &cobra.Command{ 59 | Use: "params", 60 | Short: "Query the parameters", 61 | Args: cobra.NoArgs, 62 | RunE: func(cmd *cobra.Command, args []string) error { 63 | cliCtx := context.NewCLIContext().WithCodec(cdc) 64 | 65 | route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryParameters) 66 | bz, _, err := cliCtx.QueryWithData(route, nil) 67 | if err != nil { 68 | return err 69 | } 70 | 71 | var params types.Params 72 | cdc.MustUnmarshalJSON(bz, ¶ms) 73 | return cliCtx.PrintOutput(params) 74 | }, 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /x/credit/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | "github.com/cosmos/cosmos-sdk/client/context" 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | "github.com/cosmos/cosmos-sdk/codec" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | "github.com/cosmos/cosmos-sdk/x/auth" 14 | "github.com/cosmos/cosmos-sdk/x/auth/client/utils" 15 | "github.com/mesg-foundation/engine/x/credit/internal/types" 16 | "github.com/spf13/cobra" 17 | ) 18 | 19 | // GetTxCmd returns the transaction commands for this module 20 | func GetTxCmd(cdc *codec.Codec) *cobra.Command { 21 | creditTxCmd := &cobra.Command{ 22 | Use: types.ModuleName, 23 | Short: fmt.Sprintf("%s transactions subcommands", strings.Title(types.ModuleName)), 24 | DisableFlagParsing: true, 25 | SuggestionsMinimumDistance: 2, 26 | RunE: client.ValidateCmd, 27 | } 28 | 29 | creditTxCmd.AddCommand(flags.PostCommands( 30 | GetCmdAdd(cdc), 31 | )...) 32 | return creditTxCmd 33 | } 34 | 35 | // GetCmdAdd is the command to create a execution. 36 | func GetCmdAdd(cdc *codec.Codec) *cobra.Command { 37 | return &cobra.Command{ 38 | Use: "add [address] [amount]", 39 | Short: "Add credits to an address", 40 | Args: cobra.ExactArgs(2), 41 | RunE: func(cmd *cobra.Command, args []string) error { 42 | inBuf := bufio.NewReader(cmd.InOrStdin()) 43 | cliCtx := context.NewCLIContext().WithCodec(cdc) 44 | 45 | txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 46 | 47 | address, err := sdk.AccAddressFromBech32(args[0]) 48 | if err != nil { 49 | return fmt.Errorf("address: %w", err) 50 | } 51 | amount, ok := sdk.NewIntFromString(args[1]) 52 | if !ok { 53 | return fmt.Errorf("cannot parse amount") 54 | } 55 | if cliCtx.FromAddress.Empty() { 56 | return fmt.Errorf("flag --from is required") 57 | } 58 | 59 | msg := types.MsgAdd{ 60 | Address: address, 61 | Amount: amount, 62 | Signer: cliCtx.FromAddress, 63 | } 64 | if err := msg.ValidateBasic(); err != nil { 65 | return err 66 | } 67 | 68 | return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) 69 | }, 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /x/credit/client/rest/query.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/cosmos/cosmos-sdk/client/context" 8 | "github.com/cosmos/cosmos-sdk/types/rest" 9 | "github.com/gorilla/mux" 10 | "github.com/mesg-foundation/engine/x/credit/internal/types" 11 | ) 12 | 13 | func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) { 14 | r.HandleFunc( 15 | "/credit/get/{address}", 16 | queryGetHandlerFn(cliCtx), 17 | ).Methods(http.MethodGet) 18 | 19 | r.HandleFunc( 20 | "/execution/parameters", 21 | queryParamsHandlerFn(cliCtx), 22 | ).Methods("GET") 23 | } 24 | 25 | func queryGetHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { 26 | return func(w http.ResponseWriter, r *http.Request) { 27 | vars := mux.Vars(r) 28 | 29 | cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) 30 | if !ok { 31 | return 32 | } 33 | 34 | route := fmt.Sprintf("custom/%s/%s/%s", types.QuerierRoute, types.QueryGet, vars["address"]) 35 | 36 | res, height, err := cliCtx.QueryWithData(route, nil) 37 | if err != nil { 38 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 39 | return 40 | } 41 | 42 | cliCtx = cliCtx.WithHeight(height) 43 | rest.PostProcessResponse(w, cliCtx, res) 44 | } 45 | } 46 | 47 | func queryParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { 48 | return func(w http.ResponseWriter, r *http.Request) { 49 | cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) 50 | if !ok { 51 | return 52 | } 53 | 54 | route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryParameters) 55 | 56 | res, height, err := cliCtx.QueryWithData(route, nil) 57 | if err != nil { 58 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 59 | return 60 | } 61 | 62 | cliCtx = cliCtx.WithHeight(height) 63 | rest.PostProcessResponse(w, cliCtx, res) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /x/credit/client/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | // RegisterRoutes registers ownership-related REST handlers to a router 9 | func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { 10 | registerQueryRoutes(cliCtx, r) 11 | registerTxRoutes(cliCtx, r) 12 | } 13 | -------------------------------------------------------------------------------- /x/credit/client/rest/tx.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { 9 | } 10 | -------------------------------------------------------------------------------- /x/credit/genesis.go: -------------------------------------------------------------------------------- 1 | package credit 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/x/credit/internal/types" 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | ) 8 | 9 | // InitGenesis initialize the keeper with the data from the genesis file. 10 | func InitGenesis(ctx sdk.Context, k Keeper, data types.GenesisState) []abci.ValidatorUpdate { 11 | if err := k.Import(ctx, data.Credits); err != nil { 12 | panic(err) 13 | } 14 | k.SetParams(ctx, data.Params) 15 | return []abci.ValidatorUpdate{} 16 | } 17 | 18 | // ExportGenesis writes the current store values to a genesis file, which can be imported again with InitGenesis. 19 | func ExportGenesis(ctx sdk.Context, k Keeper) (data types.GenesisState) { 20 | params := k.GetParams(ctx) 21 | execs, err := k.Export(ctx) 22 | if err != nil { 23 | panic(err) 24 | } 25 | return types.NewGenesisState(params, execs) 26 | } 27 | -------------------------------------------------------------------------------- /x/credit/handler.go: -------------------------------------------------------------------------------- 1 | package credit 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 8 | "github.com/mesg-foundation/engine/x/credit/internal/types" 9 | ) 10 | 11 | // NewHandler creates an sdk.Handler for all the instance type messages 12 | func NewHandler(k Keeper) sdk.Handler { 13 | return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 14 | ctx = ctx.WithEventManager(sdk.NewEventManager()) 15 | switch msg := msg.(type) { 16 | case MsgAdd: 17 | return handleMsgAdd(ctx, k, msg) 18 | default: 19 | errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) 20 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) 21 | } 22 | } 23 | } 24 | 25 | // handleMsgAdd adds credits to an address. 26 | func handleMsgAdd(ctx sdk.Context, k Keeper, msg MsgAdd) (*sdk.Result, error) { 27 | // check if signer is a minter 28 | minters := k.Minters(ctx) 29 | isMinter := false 30 | for _, minter := range minters { 31 | if msg.Signer.Equals(minter) { 32 | isMinter = true 33 | break 34 | } 35 | } 36 | if !isMinter { 37 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "the signer is not a minter") 38 | } 39 | if _, err := k.Add(ctx, msg.Address, msg.Amount); err != nil { 40 | return nil, err 41 | } 42 | ctx.EventManager().EmitEvent( 43 | sdk.NewEvent( 44 | sdk.EventTypeMessage, 45 | sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), 46 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer.String()), 47 | ), 48 | ) 49 | 50 | return &sdk.Result{ 51 | Events: ctx.EventManager().Events(), 52 | }, nil 53 | } 54 | -------------------------------------------------------------------------------- /x/credit/internal/keeper/params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/x/credit/internal/types" 6 | ) 7 | 8 | // Default parameter namespace 9 | const ( 10 | DefaultParamspace = types.ModuleName 11 | ) 12 | 13 | // Minters are authorized account that can add credits to any address. 14 | func (k Keeper) Minters(ctx sdk.Context) []sdk.AccAddress { 15 | var minters []sdk.AccAddress 16 | k.paramstore.Get(ctx, types.KeyMinters, &minters) 17 | return minters 18 | } 19 | 20 | // SetParams will populate all the params 21 | func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { 22 | k.paramstore.SetParamSet(ctx, ¶ms) 23 | } 24 | 25 | // GetParams returns all the params of the module 26 | func (k Keeper) GetParams(ctx sdk.Context) types.Params { 27 | var params types.Params 28 | k.paramstore.GetParamSet(ctx, ¶ms) 29 | return params 30 | } 31 | -------------------------------------------------------------------------------- /x/credit/internal/keeper/querier.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/x/credit/internal/types" 7 | abci "github.com/tendermint/tendermint/abci/types" 8 | ) 9 | 10 | // NewQuerier creates a new querier for credit clients. 11 | func NewQuerier(k Keeper) sdk.Querier { 12 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { 13 | switch path[0] { 14 | case types.QueryGet: 15 | return get(ctx, k, path[1]) 16 | case types.QueryParameters: 17 | return queryParameters(ctx, k) 18 | default: 19 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown credit query endpoint") 20 | } 21 | } 22 | } 23 | 24 | func get(ctx sdk.Context, k Keeper, address string) ([]byte, error) { 25 | addr, err := sdk.AccAddressFromBech32(address) 26 | if err != nil { 27 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 28 | } 29 | value, err := k.Get(ctx, addr) 30 | if err != nil { 31 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 32 | } 33 | res, err := types.ModuleCdc.MarshalJSON(value) 34 | if err != nil { 35 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 36 | } 37 | return res, nil 38 | } 39 | 40 | func queryParameters(ctx sdk.Context, k Keeper) ([]byte, error) { 41 | res, err := types.ModuleCdc.MarshalJSON(k.GetParams(ctx)) 42 | if err != nil { 43 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 44 | } 45 | return res, nil 46 | } 47 | -------------------------------------------------------------------------------- /x/credit/internal/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // RegisterCodec registers concrete types on codec. 8 | func RegisterCodec(cdc *codec.Codec) { 9 | cdc.RegisterConcrete(MsgAdd{}, "credit/add", nil) 10 | } 11 | 12 | // ModuleCdc defines the module codec. 13 | var ModuleCdc *codec.Codec 14 | 15 | func init() { 16 | ModuleCdc = codec.New() 17 | RegisterCodec(ModuleCdc) 18 | codec.RegisterCrypto(ModuleCdc) 19 | ModuleCdc.Seal() 20 | } 21 | -------------------------------------------------------------------------------- /x/credit/internal/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // module event types and attributes 4 | const ( 5 | EventType = "credit" 6 | 7 | AttributeKeyAddress = "address" 8 | AttributeKeyAmount = "amount" 9 | 10 | AttributeActionAdded = "added" 11 | AttributeActionSubtracted = "subtracted" 12 | ) 13 | -------------------------------------------------------------------------------- /x/credit/internal/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/cosmos/cosmos-sdk/x/auth/exported" 6 | "github.com/cosmos/cosmos-sdk/x/params" 7 | ) 8 | 9 | // ParamSubspace defines the expected Subspace interfacace 10 | type ParamSubspace interface { 11 | WithKeyTable(table params.KeyTable) params.Subspace 12 | Get(ctx sdk.Context, key []byte, ptr interface{}) 13 | GetParamSet(ctx sdk.Context, ps params.ParamSet) 14 | SetParamSet(ctx sdk.Context, ps params.ParamSet) 15 | } 16 | 17 | // AccountKeeper interface 18 | type AccountKeeper interface { 19 | NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) exported.Account 20 | GetAccount(ctx sdk.Context, addr sdk.AccAddress) exported.Account 21 | SetAccount(ctx sdk.Context, acc exported.Account) 22 | } 23 | -------------------------------------------------------------------------------- /x/credit/internal/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | fmt "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/mesg-foundation/engine/ext/xvalidator" 8 | ) 9 | 10 | // GenesisState - all instance state that must be provided at genesis 11 | type GenesisState struct { 12 | Params Params `json:"params" yaml:"params" validate:"dive"` 13 | Credits map[string]sdk.Int `json:"credits" yaml:"credits" validate:"dive,required,bigint"` 14 | } 15 | 16 | // NewGenesisState creates a new GenesisState object 17 | func NewGenesisState(params Params, credits map[string]sdk.Int) GenesisState { 18 | return GenesisState{ 19 | Params: params, 20 | Credits: credits, 21 | } 22 | } 23 | 24 | // DefaultGenesisState is the default GenesisState 25 | func DefaultGenesisState() GenesisState { 26 | return GenesisState{ 27 | Params: DefaultParams(), 28 | Credits: map[string]sdk.Int{}, 29 | } 30 | } 31 | 32 | // ValidateGenesis validates the instance genesis parameters 33 | func ValidateGenesis(data GenesisState) error { 34 | if err := xvalidator.Struct(data); err != nil { 35 | return fmt.Errorf("failed to validate %s genesis state: %w", ModuleName, err) 36 | } 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /x/credit/internal/types/key.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the module 5 | ModuleName = "credit" 6 | 7 | // StoreKey to be used when creating the KVStore 8 | StoreKey = ModuleName 9 | 10 | // RouterKey to be used for routing msgs 11 | RouterKey = ModuleName 12 | 13 | // QuerierRoute to be used for routing 14 | QuerierRoute = ModuleName 15 | ) 16 | -------------------------------------------------------------------------------- /x/credit/internal/types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | ) 8 | 9 | // Route should return the name of the module. 10 | func (msg MsgAdd) Route() string { 11 | return ModuleName 12 | } 13 | 14 | // Type returns the action. 15 | func (msg MsgAdd) Type() string { 16 | return "add" 17 | } 18 | 19 | // ValidateBasic runs stateless checks on the message. 20 | func (msg MsgAdd) ValidateBasic() error { 21 | if err := xvalidator.Struct(msg); err != nil { 22 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 23 | } 24 | return nil 25 | } 26 | 27 | // GetSignBytes encodes the message for signing. 28 | func (msg MsgAdd) GetSignBytes() []byte { 29 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 30 | } 31 | 32 | // GetSigners defines whose signature is required. 33 | func (msg MsgAdd) GetSigners() []sdk.AccAddress { 34 | return []sdk.AccAddress{msg.Signer} 35 | } 36 | -------------------------------------------------------------------------------- /x/credit/internal/types/msg.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | 5 | package mesg.credit.types; 6 | option go_package = "github.com/mesg-foundation/engine/x/credit/internal/types"; 7 | 8 | option (gogoproto.goproto_getters_all) = false; 9 | 10 | // The message to add credits. 11 | message MsgAdd { 12 | // The msg's signer. 13 | bytes signer = 1 [ 14 | (gogoproto.moretags) = 'validate:"required,accaddress"', 15 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 16 | ]; 17 | 18 | // The address to add the credits. 19 | bytes address = 2 [ 20 | (gogoproto.moretags) = 'validate:"required,accaddress"', 21 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 22 | ]; 23 | 24 | // amount of credits to add. 25 | string amount = 3 [ 26 | (gogoproto.moretags) = 'hash:"name:1" validate:"required,bigint"', 27 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.Int" 28 | ]; 29 | } 30 | -------------------------------------------------------------------------------- /x/credit/internal/types/params.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/x/params" 8 | "github.com/cosmos/cosmos-sdk/x/params/subspace" 9 | ) 10 | 11 | // Default parameter namespace 12 | const ( 13 | DefaultParamspace = ModuleName 14 | ) 15 | 16 | var ( 17 | // KeyMinters key for the parameter Minters 18 | KeyMinters = []byte("Minters") 19 | 20 | // DefaultMinters is the default value of Minters 21 | DefaultMinters = []sdk.AccAddress{} 22 | ) 23 | 24 | // Params - used for initializing default parameter for instance at genesis 25 | type Params struct { 26 | Minters []sdk.AccAddress `json:"minters" yaml:"minters"` 27 | } 28 | 29 | // NewParams creates a new Params object 30 | func NewParams(minters []sdk.AccAddress) Params { 31 | return Params{ 32 | Minters: minters, 33 | } 34 | } 35 | 36 | // ParamKeyTable for auth module 37 | func ParamKeyTable() subspace.KeyTable { 38 | return subspace.NewKeyTable().RegisterParamSet(&Params{}) 39 | } 40 | 41 | // String implements the stringer interface for Params 42 | func (p Params) String() string { 43 | return fmt.Sprintf(`Params: 44 | Minters: %s 45 | `, p.Minters) 46 | } 47 | 48 | // ParamSetPairs - Implements params.ParamSet 49 | func (p *Params) ParamSetPairs() params.ParamSetPairs { 50 | return params.ParamSetPairs{ 51 | params.NewParamSetPair(KeyMinters, &p.Minters, validateMinters), 52 | } 53 | } 54 | 55 | // DefaultParams defines the parameters for this module 56 | func DefaultParams() Params { 57 | return NewParams(DefaultMinters) 58 | } 59 | 60 | func validateMinters(i interface{}) error { 61 | minters, ok := i.([]sdk.AccAddress) 62 | if !ok { 63 | return fmt.Errorf("invalid parameter type: %T", i) 64 | } 65 | for _, minter := range minters { 66 | if err := sdk.VerifyAddressFormat(minter); err != nil { 67 | return err 68 | } 69 | } 70 | return nil 71 | } 72 | -------------------------------------------------------------------------------- /x/credit/internal/types/querier.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Query endpoints supported by the ownership querier 4 | const ( 5 | QueryGet = "get" 6 | QueryParameters = "parameters" 7 | ) 8 | -------------------------------------------------------------------------------- /x/execution/abci.go: -------------------------------------------------------------------------------- 1 | package execution 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // BeginBlocker check for infraction evidence or downtime of validators 9 | // on every begin block 10 | func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {} 11 | 12 | // EndBlocker called every block, process inflation, update validator set. 13 | func EndBlocker(ctx sdk.Context, k Keeper) {} 14 | -------------------------------------------------------------------------------- /x/execution/alias.go: -------------------------------------------------------------------------------- 1 | package execution 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/x/execution/internal/keeper" 5 | "github.com/mesg-foundation/engine/x/execution/internal/types" 6 | ) 7 | 8 | // const aliases 9 | const ( 10 | ModuleName = types.ModuleName 11 | RouterKey = types.RouterKey 12 | StoreKey = types.StoreKey 13 | QuerierRoute = types.QuerierRoute 14 | ) 15 | 16 | // functions and variable aliases 17 | var ( 18 | NewKeeper = keeper.NewKeeper 19 | NewQuerier = keeper.NewQuerier 20 | RegisterCodec = types.RegisterCodec 21 | NewGenesisState = types.NewGenesisState 22 | DefaultGenesisState = types.DefaultGenesisState 23 | ValidateGenesis = types.ValidateGenesis 24 | 25 | ModuleCdc = types.ModuleCdc 26 | 27 | QueryGet = types.QueryGet 28 | QueryList = types.QueryList 29 | 30 | M = keeper.M 31 | 32 | EventType = types.EventType 33 | AttributeKeyHash = types.AttributeKeyHash 34 | AttributeKeyAddress = types.AttributeKeyAddress 35 | AttributeKeyExecutor = types.AttributeKeyExecutor 36 | AttributeKeyProcess = types.AttributeKeyProcess 37 | AttributeKeyInstance = types.AttributeKeyInstance 38 | AttributeActionProposed = types.AttributeActionProposed 39 | AttributeActionCreated = types.AttributeActionCreated 40 | AttributeActionCompleted = types.AttributeActionCompleted 41 | AttributeActionFailed = types.AttributeActionFailed 42 | ) 43 | 44 | // module types 45 | type ( 46 | Keeper = keeper.Keeper 47 | GenesisState = types.GenesisState 48 | 49 | MsgCreate = types.MsgCreate 50 | MsgUpdate = types.MsgUpdate 51 | MsgUpdateOutputs = types.MsgUpdate_Outputs 52 | MsgUpdateError = types.MsgUpdate_Error 53 | ) 54 | -------------------------------------------------------------------------------- /x/execution/client/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | // RegisterRoutes registers execution-related REST handlers to a router 9 | func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { 10 | registerQueryRoutes(cliCtx, r) 11 | registerTxRoutes(cliCtx, r) 12 | } 13 | -------------------------------------------------------------------------------- /x/execution/client/rest/tx.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) {} 9 | -------------------------------------------------------------------------------- /x/execution/genesis.go: -------------------------------------------------------------------------------- 1 | package execution 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/x/execution/internal/types" 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | ) 8 | 9 | // InitGenesis initialize the keeper with the data from the genesis file. 10 | func InitGenesis(ctx sdk.Context, k Keeper, data types.GenesisState) []abci.ValidatorUpdate { 11 | if err := k.Import(ctx, data.Executions); err != nil { 12 | panic(err) 13 | } 14 | return []abci.ValidatorUpdate{} 15 | } 16 | 17 | // ExportGenesis writes the current store values to a genesis file, which can be imported again with InitGenesis. 18 | func ExportGenesis(ctx sdk.Context, k Keeper) (data types.GenesisState) { 19 | execs, err := k.List(ctx, types.ListFilter{}) 20 | if err != nil { 21 | panic(err) 22 | } 23 | return types.NewGenesisState(execs) 24 | } 25 | -------------------------------------------------------------------------------- /x/execution/handler.go: -------------------------------------------------------------------------------- 1 | package execution 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/x/execution/internal/types" 7 | ) 8 | 9 | // NewHandler creates an sdk.Handler for all the execution type messages 10 | func NewHandler(k Keeper) sdk.Handler { 11 | return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 12 | ctx = ctx.WithEventManager(sdk.NewEventManager()) 13 | switch msg := msg.(type) { 14 | case MsgCreate: 15 | return handleMsgCreate(ctx, k, msg) 16 | case MsgUpdate: 17 | return handleMsgUpdate(ctx, k, msg) 18 | default: 19 | return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg) 20 | } 21 | } 22 | } 23 | 24 | // handleMsgCreate creates a new execution. 25 | func handleMsgCreate(ctx sdk.Context, k Keeper, msg MsgCreate) (*sdk.Result, error) { 26 | exec, err := k.Create(ctx, msg) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | ctx.EventManager().EmitEvent( 32 | sdk.NewEvent( 33 | sdk.EventTypeMessage, 34 | sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), 35 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer.String()), 36 | ), 37 | ) 38 | 39 | return &sdk.Result{ 40 | Data: exec.Hash, 41 | Events: ctx.EventManager().Events(), 42 | }, nil 43 | } 44 | 45 | // handleMsgUpdate updates an execution. 46 | func handleMsgUpdate(ctx sdk.Context, k Keeper, msg MsgUpdate) (*sdk.Result, error) { 47 | exec, err := k.Update(ctx, msg) 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | ctx.EventManager().EmitEvent( 53 | sdk.NewEvent( 54 | sdk.EventTypeMessage, 55 | sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), 56 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Executor.String()), 57 | ), 58 | ) 59 | 60 | return &sdk.Result{ 61 | Data: exec.Hash, 62 | Events: ctx.EventManager().Events(), 63 | }, nil 64 | } 65 | -------------------------------------------------------------------------------- /x/execution/internal/keeper/metrics.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/go-kit/kit/metrics" 5 | prometheus "github.com/go-kit/kit/metrics/prometheus" 6 | stdprometheus "github.com/prometheus/client_golang/prometheus" 7 | ) 8 | 9 | // M is global metric variable. 10 | var M = NewMetric() 11 | 12 | // Metric is struct to keep counters for execution statuses. 13 | type Metric struct { 14 | Created metrics.Counter 15 | InProgress metrics.Counter 16 | Updated metrics.Counter 17 | Completed metrics.Counter 18 | } 19 | 20 | // NewMetric creates a counters metric. 21 | func NewMetric() *Metric { 22 | return &Metric{ 23 | Created: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 24 | Namespace: "mesg", 25 | Subsystem: "execution", 26 | Name: "created", 27 | Help: "executions created", 28 | }, []string{}), 29 | InProgress: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 30 | Namespace: "mesg", 31 | Subsystem: "execution", 32 | Name: "in_progress", 33 | Help: "executions in progress", 34 | }, []string{}), 35 | Updated: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 36 | Namespace: "mesg", 37 | Subsystem: "execution", 38 | Name: "updated", 39 | Help: "executions updated", 40 | }, []string{}), 41 | Completed: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 42 | Namespace: "mesg", 43 | Subsystem: "execution", 44 | Name: "completed", 45 | Help: "executions completed", 46 | }, []string{}), 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /x/execution/internal/keeper/querier.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/hash" 7 | "github.com/mesg-foundation/engine/x/execution/internal/types" 8 | abci "github.com/tendermint/tendermint/abci/types" 9 | ) 10 | 11 | // NewQuerier creates a new querier for execution clients. 12 | func NewQuerier(k Keeper) sdk.Querier { 13 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { 14 | switch path[0] { 15 | case types.QueryGet: 16 | return get(ctx, k, path[1:]) 17 | case types.QueryList: 18 | return list(ctx, k, req.Data) 19 | default: 20 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown execution query endpoint") 21 | } 22 | } 23 | } 24 | 25 | func get(ctx sdk.Context, k Keeper, path []string) ([]byte, error) { 26 | if len(path) == 0 { 27 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing hash") 28 | } 29 | hash, err := hash.Decode(path[0]) 30 | if err != nil { 31 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 32 | } 33 | 34 | e, err := k.Get(ctx, hash) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | res, err := types.ModuleCdc.MarshalJSON(e) 40 | if err != nil { 41 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 42 | } 43 | return res, nil 44 | } 45 | 46 | func list(ctx sdk.Context, k Keeper, data []byte) ([]byte, error) { 47 | var filter types.ListFilter 48 | if err := types.ModuleCdc.UnmarshalJSON(data, &filter); err != nil { 49 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) 50 | } 51 | es, err := k.List(ctx, filter) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | res, err := types.ModuleCdc.MarshalJSON(es) 57 | if err != nil { 58 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 59 | } 60 | return res, nil 61 | } 62 | -------------------------------------------------------------------------------- /x/execution/internal/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | "github.com/mesg-foundation/engine/protobuf/types" 6 | ) 7 | 8 | // RegisterCodec registers concrete types on codec 9 | func RegisterCodec(cdc *codec.Codec) { 10 | cdc.RegisterConcrete(MsgCreate{}, "execution/create", nil) 11 | cdc.RegisterConcrete(MsgUpdate{}, "execution/update", nil) 12 | cdc.RegisterInterface((*isMsgUpdate_Result)(nil), nil) 13 | cdc.RegisterConcrete(&MsgUpdate_Outputs{}, "mesg.execution.types.MsgUpdate_Outputs", nil) 14 | cdc.RegisterConcrete(&MsgUpdate_Error{}, "mesg.execution.types.MsgUpdate_Error", nil) 15 | } 16 | 17 | // ModuleCdc defines the module codec 18 | var ModuleCdc *codec.Codec 19 | 20 | func init() { 21 | ModuleCdc = codec.New() 22 | RegisterCodec(ModuleCdc) 23 | types.RegisterCodec(ModuleCdc) 24 | codec.RegisterCrypto(ModuleCdc) 25 | ModuleCdc.Seal() 26 | } 27 | -------------------------------------------------------------------------------- /x/execution/internal/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // module event types and attributes 4 | const ( 5 | EventType = "execution" 6 | 7 | AttributeKeyHash = "hash" 8 | AttributeKeyAddress = "address" 9 | AttributeKeyExecutor = "executor" 10 | AttributeKeyProcess = "process" 11 | AttributeKeyInstance = "instance" 12 | 13 | AttributeActionProposed = "proposed" 14 | AttributeActionCreated = "created" 15 | AttributeActionCompleted = "completed" 16 | AttributeActionFailed = "failed" 17 | ) 18 | -------------------------------------------------------------------------------- /x/execution/internal/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/hash" 6 | instancepb "github.com/mesg-foundation/engine/instance" 7 | processpb "github.com/mesg-foundation/engine/process" 8 | runnerpb "github.com/mesg-foundation/engine/runner" 9 | servicepb "github.com/mesg-foundation/engine/service" 10 | ) 11 | 12 | // ServiceKeeper module interface. 13 | type ServiceKeeper interface { 14 | Get(ctx sdk.Context, hash hash.Hash) (*servicepb.Service, error) 15 | } 16 | 17 | // InstanceKeeper module interface. 18 | type InstanceKeeper interface { 19 | Get(ctx sdk.Context, instanceHash hash.Hash) (*instancepb.Instance, error) 20 | } 21 | 22 | // RunnerKeeper module interface. 23 | type RunnerKeeper interface { 24 | Get(ctx sdk.Context, hash hash.Hash) (*runnerpb.Runner, error) 25 | List(ctx sdk.Context) ([]*runnerpb.Runner, error) 26 | } 27 | 28 | // ProcessKeeper module interface. 29 | type ProcessKeeper interface { 30 | Get(ctx sdk.Context, hash hash.Hash) (*processpb.Process, error) 31 | } 32 | 33 | // CreditKeeper module interface. 34 | type CreditKeeper interface { 35 | Sub(ctx sdk.Context, address sdk.AccAddress, amount sdk.Int) (sdk.Int, error) 36 | } 37 | -------------------------------------------------------------------------------- /x/execution/internal/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | fmt "fmt" 5 | 6 | executionpb "github.com/mesg-foundation/engine/execution" 7 | "github.com/mesg-foundation/engine/ext/xvalidator" 8 | ) 9 | 10 | // GenesisState - all instance state that must be provided at genesis 11 | type GenesisState struct { 12 | Executions []*executionpb.Execution `json:"executions" yaml:"executions" validate:"dive"` 13 | } 14 | 15 | // NewGenesisState creates a new GenesisState object 16 | func NewGenesisState(execs []*executionpb.Execution) GenesisState { 17 | return GenesisState{ 18 | Executions: execs, 19 | } 20 | } 21 | 22 | // DefaultGenesisState is the default GenesisState 23 | func DefaultGenesisState() GenesisState { 24 | return GenesisState{ 25 | Executions: []*executionpb.Execution{}, 26 | } 27 | } 28 | 29 | // ValidateGenesis validates the instance genesis parameters 30 | func ValidateGenesis(data GenesisState) error { 31 | if err := xvalidator.Struct(data); err != nil { 32 | return fmt.Errorf("failed to validate %s genesis state: %w", ModuleName, err) 33 | } 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /x/execution/internal/types/key.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the module 5 | ModuleName = "execution" 6 | 7 | // StoreKey to be used when creating the KVStore 8 | StoreKey = ModuleName 9 | 10 | // RouterKey to be used for routing msgs 11 | RouterKey = ModuleName 12 | 13 | // QuerierRoute to be used for routing 14 | QuerierRoute = ModuleName 15 | ) 16 | -------------------------------------------------------------------------------- /x/execution/internal/types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | ) 8 | 9 | // Route should return the name of the module. 10 | func (msg MsgCreate) Route() string { 11 | return ModuleName 12 | } 13 | 14 | // Type returns the action. 15 | func (msg MsgCreate) Type() string { 16 | return "create" 17 | } 18 | 19 | // ValidateBasic runs stateless checks on the message. 20 | func (msg MsgCreate) ValidateBasic() error { 21 | if err := xvalidator.Struct(msg); err != nil { 22 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 23 | } 24 | return nil 25 | } 26 | 27 | // GetSignBytes encodes the message for signing. 28 | func (msg MsgCreate) GetSignBytes() []byte { 29 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 30 | } 31 | 32 | // GetSigners defines whose signature is required. 33 | func (msg MsgCreate) GetSigners() []sdk.AccAddress { 34 | return []sdk.AccAddress{msg.Signer} 35 | } 36 | 37 | // Route should return the name of the module. 38 | func (msg MsgUpdate) Route() string { 39 | return ModuleName 40 | } 41 | 42 | // Type returns the action. 43 | func (msg MsgUpdate) Type() string { 44 | return "update" 45 | } 46 | 47 | // ValidateBasic runs stateless checks on the message. 48 | func (msg MsgUpdate) ValidateBasic() error { 49 | if err := xvalidator.Struct(msg); err != nil { 50 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 51 | } 52 | return nil 53 | } 54 | 55 | // GetSignBytes encodes the message for signing. 56 | func (msg MsgUpdate) GetSignBytes() []byte { 57 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 58 | } 59 | 60 | // GetSigners defines whose signature is required. 61 | func (msg MsgUpdate) GetSigners() []sdk.AccAddress { 62 | return []sdk.AccAddress{msg.Executor} 63 | } 64 | -------------------------------------------------------------------------------- /x/execution/internal/types/msg.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | import "protobuf/types/struct.proto"; 5 | 6 | package mesg.execution.types; 7 | option go_package = "github.com/mesg-foundation/engine/x/execution/internal/types"; 8 | 9 | // The message to create an Execution. 10 | message MsgCreate { 11 | // The msg's signer. 12 | bytes signer = 1 [ 13 | (gogoproto.moretags) = 'validate:"required,accaddress"', 14 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 15 | ]; 16 | 17 | // taskKey to filter executions. 18 | string taskKey = 2 [ 19 | (gogoproto.moretags) = 'validate:"required,printascii"' 20 | ]; 21 | 22 | mesg.protobuf.Struct inputs = 3; 23 | 24 | // tags the execution. 25 | repeated string tags = 4 [ 26 | (gogoproto.moretags) = 'validate:"dive,printascii"' 27 | ]; 28 | 29 | bytes parentHash = 5 [ 30 | (gogoproto.moretags) = 'validate:"required_without=EventHash,omitempty,hash"', 31 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 32 | ]; 33 | 34 | bytes eventHash = 6 [ 35 | (gogoproto.moretags) = 'validate:"required_without=ParentHash,omitempty,hash"', 36 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 37 | ]; 38 | 39 | bytes processHash = 7 [ 40 | (gogoproto.moretags) = 'validate:"omitempty,hash"', 41 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 42 | ]; 43 | 44 | string nodeKey = 8; 45 | 46 | bytes executorHash = 9 [ 47 | (gogoproto.moretags) = 'validate:"required,hash"', 48 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 49 | ]; 50 | } 51 | 52 | // The message to update an Execution. 53 | message MsgUpdate { 54 | // The execution's executor. 55 | bytes executor = 1 [ 56 | (gogoproto.moretags) = 'validate:"required,accaddress"', 57 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 58 | ]; 59 | 60 | // Hash represents execution. 61 | bytes hash = 2 [ 62 | (gogoproto.moretags) = 'validate:"required,hash"', 63 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 64 | ]; 65 | 66 | // result pass to execution 67 | oneof result { 68 | // outputs is a success result. 69 | mesg.protobuf.Struct outputs = 3; 70 | 71 | // error is an error result. 72 | string error = 4; 73 | } 74 | 75 | // Start time in nanoseconds. 76 | int64 start = 5 [ 77 | (gogoproto.moretags) = 'validate:"required"' 78 | ]; 79 | 80 | // Stop time in nanoseconds. 81 | int64 stop = 6 [ 82 | (gogoproto.moretags) = 'validate:"required,gtfield=Start"' 83 | ]; 84 | } 85 | -------------------------------------------------------------------------------- /x/execution/internal/types/querier.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/execution" 5 | "github.com/mesg-foundation/engine/hash" 6 | ) 7 | 8 | // Querier names 9 | const ( 10 | QueryGet = "get" 11 | QueryList = "list" 12 | ) 13 | 14 | // ListFilter available for the List 15 | type ListFilter struct { 16 | ParentHash hash.Hash `json:"parentHash"` 17 | EventHash hash.Hash `json:"eventHash"` 18 | InstanceHash hash.Hash `json:"instanceHash"` 19 | ProcessHash hash.Hash `json:"processHash"` 20 | Status execution.Status `json:"status"` 21 | NodeKey string `json:"nodeKey"` 22 | } 23 | 24 | // Match returns true if an execution matches a specific filter 25 | func (f ListFilter) Match(exec *execution.Execution) bool { 26 | if f.Status != execution.Status_Unknown && f.Status != exec.Status { 27 | return false 28 | } 29 | if !f.ProcessHash.IsZero() && !f.ProcessHash.Equal(exec.ProcessHash) { 30 | return false 31 | } 32 | if !f.InstanceHash.IsZero() && !f.InstanceHash.Equal(exec.InstanceHash) { 33 | return false 34 | } 35 | if !f.ParentHash.IsZero() && !f.ParentHash.Equal(exec.ParentHash) { 36 | return false 37 | } 38 | if !f.EventHash.IsZero() && !f.EventHash.Equal(exec.EventHash) { 39 | return false 40 | } 41 | if f.NodeKey != "" && f.NodeKey != exec.NodeKey { 42 | return false 43 | } 44 | return true 45 | } 46 | -------------------------------------------------------------------------------- /x/instance/abci.go: -------------------------------------------------------------------------------- 1 | package instance 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // BeginBlocker check for infraction evidence or downtime of validators 9 | // on every begin block 10 | func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {} 11 | 12 | // EndBlocker called every block, process inflation, update validator set. 13 | func EndBlocker(ctx sdk.Context, k Keeper) {} 14 | -------------------------------------------------------------------------------- /x/instance/alias.go: -------------------------------------------------------------------------------- 1 | package instance 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/x/instance/internal/keeper" 5 | "github.com/mesg-foundation/engine/x/instance/internal/types" 6 | ) 7 | 8 | // const aliases 9 | const ( 10 | ModuleName = types.ModuleName 11 | RouterKey = types.RouterKey 12 | StoreKey = types.StoreKey 13 | QuerierRoute = types.QuerierRoute 14 | ) 15 | 16 | // functions and variable aliases 17 | var ( 18 | NewKeeper = keeper.NewKeeper 19 | NewQuerier = keeper.NewQuerier 20 | RegisterCodec = types.RegisterCodec 21 | NewGenesisState = types.NewGenesisState 22 | DefaultGenesisState = types.DefaultGenesisState 23 | ValidateGenesis = types.ValidateGenesis 24 | 25 | ModuleCdc = types.ModuleCdc 26 | QueryGet = types.QueryGet 27 | QueryList = types.QueryList 28 | 29 | EventType = types.EventType 30 | AttributeKeyHash = types.AttributeKeyHash 31 | AttributeKeyService = types.AttributeKeyService 32 | AttributeActionCreated = types.AttributeActionCreated 33 | ) 34 | 35 | // module types 36 | type ( 37 | Keeper = keeper.Keeper 38 | GenesisState = types.GenesisState 39 | ) 40 | -------------------------------------------------------------------------------- /x/instance/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/context" 8 | "github.com/cosmos/cosmos-sdk/client/flags" 9 | "github.com/cosmos/cosmos-sdk/codec" 10 | "github.com/mesg-foundation/engine/instance" 11 | "github.com/mesg-foundation/engine/x/instance/internal/types" 12 | "github.com/spf13/cobra" 13 | ) 14 | 15 | // GetQueryCmd returns the cli query commands for this module 16 | func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { 17 | // Group instance queries under a subcommand 18 | instanceQueryCmd := &cobra.Command{ 19 | Use: types.ModuleName, 20 | Short: fmt.Sprintf("Query commands for the %s module", types.ModuleName), 21 | DisableFlagParsing: true, 22 | SuggestionsMinimumDistance: 2, 23 | RunE: client.ValidateCmd, 24 | } 25 | 26 | instanceQueryCmd.AddCommand( 27 | flags.GetCommands( 28 | GetCmdGet(queryRoute, cdc), 29 | GetCmdList(queryRoute, cdc), 30 | )..., 31 | ) 32 | 33 | return instanceQueryCmd 34 | } 35 | 36 | // GetCmdGet implements the get query command. 37 | func GetCmdGet(queryRoute string, cdc *codec.Codec) *cobra.Command { 38 | return &cobra.Command{ 39 | Use: "get [hash]", 40 | Short: "Fetch an instance by its hash", 41 | Args: cobra.ExactArgs(1), 42 | RunE: func(cmd *cobra.Command, args []string) error { 43 | cliCtx := context.NewCLIContext().WithCodec(cdc) 44 | res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", queryRoute, types.QueryGet, args[0]), nil) 45 | if err != nil { 46 | fmt.Printf("could not get instance\n%s\n", err.Error()) 47 | return nil 48 | } 49 | 50 | var out *instance.Instance 51 | cdc.MustUnmarshalJSON(res, &out) 52 | return cliCtx.PrintOutput(out) 53 | }, 54 | } 55 | } 56 | 57 | // GetCmdList implements the list query command. 58 | func GetCmdList(queryRoute string, cdc *codec.Codec) *cobra.Command { 59 | return &cobra.Command{ 60 | Use: "list", 61 | Short: "Query all the instances", 62 | Args: cobra.NoArgs, 63 | RunE: func(cmd *cobra.Command, args []string) error { 64 | cliCtx := context.NewCLIContext().WithCodec(cdc) 65 | res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryList), nil) 66 | if err != nil { 67 | fmt.Printf("could not list instances\n%s\n", err.Error()) 68 | return nil 69 | } 70 | 71 | var out []*instance.Instance 72 | cdc.MustUnmarshalJSON(res, &out) 73 | return cliCtx.PrintOutput(out) 74 | }, 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /x/instance/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | // GetTxCmd returns the transaction commands for this module 9 | func GetTxCmd(cdc *codec.Codec) *cobra.Command { 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /x/instance/client/rest/query.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/cosmos/cosmos-sdk/client/context" 8 | "github.com/cosmos/cosmos-sdk/types/rest" 9 | "github.com/gorilla/mux" 10 | "github.com/mesg-foundation/engine/x/instance/internal/types" 11 | ) 12 | 13 | func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) { 14 | r.HandleFunc( 15 | "/instance/get/{hash}", 16 | queryGetHandlerFn(cliCtx), 17 | ).Methods(http.MethodGet) 18 | 19 | r.HandleFunc( 20 | "/instance/list", 21 | queryListHandlerFn(cliCtx), 22 | ).Methods(http.MethodGet) 23 | } 24 | 25 | func queryGetHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { 26 | return func(w http.ResponseWriter, r *http.Request) { 27 | vars := mux.Vars(r) 28 | 29 | cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) 30 | if !ok { 31 | return 32 | } 33 | 34 | route := fmt.Sprintf("custom/%s/%s/%s", types.QuerierRoute, types.QueryGet, vars["hash"]) 35 | 36 | res, height, err := cliCtx.QueryWithData(route, nil) 37 | if err != nil { 38 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 39 | return 40 | } 41 | 42 | cliCtx = cliCtx.WithHeight(height) 43 | rest.PostProcessResponse(w, cliCtx, res) 44 | } 45 | } 46 | 47 | func queryListHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { 48 | return func(w http.ResponseWriter, r *http.Request) { 49 | cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) 50 | if !ok { 51 | return 52 | } 53 | 54 | route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryList) 55 | 56 | res, height, err := cliCtx.QueryWithData(route, nil) 57 | if err != nil { 58 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 59 | return 60 | } 61 | 62 | cliCtx = cliCtx.WithHeight(height) 63 | rest.PostProcessResponse(w, cliCtx, res) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /x/instance/client/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | // RegisterRoutes registers instance-related REST handlers to a router 9 | func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { 10 | registerQueryRoutes(cliCtx, r) 11 | registerTxRoutes(cliCtx, r) 12 | } 13 | -------------------------------------------------------------------------------- /x/instance/client/rest/tx.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) {} 9 | -------------------------------------------------------------------------------- /x/instance/genesis.go: -------------------------------------------------------------------------------- 1 | package instance 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/x/instance/internal/types" 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | ) 8 | 9 | // InitGenesis initialize default parameters and the keeper's address to pubkey map. 10 | func InitGenesis(ctx sdk.Context, k Keeper, data types.GenesisState) []abci.ValidatorUpdate { 11 | if err := k.Import(ctx, data.Instances); err != nil { 12 | panic(err) 13 | } 14 | return []abci.ValidatorUpdate{} 15 | } 16 | 17 | // ExportGenesis writes the current store values // to a genesis file, 18 | // which can be imported again with InitGenesis. 19 | func ExportGenesis(ctx sdk.Context, k Keeper) types.GenesisState { 20 | instances, err := k.List(ctx) 21 | if err != nil { 22 | panic(err) 23 | } 24 | return types.NewGenesisState(instances) 25 | } 26 | -------------------------------------------------------------------------------- /x/instance/handler.go: -------------------------------------------------------------------------------- 1 | package instance 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 8 | "github.com/mesg-foundation/engine/x/instance/internal/types" 9 | ) 10 | 11 | // NewHandler creates an sdk.Handler for all the instance type messages 12 | func NewHandler(k Keeper) sdk.Handler { 13 | return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 14 | errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) 15 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /x/instance/internal/keeper/querier.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/hash" 7 | "github.com/mesg-foundation/engine/x/instance/internal/types" 8 | abci "github.com/tendermint/tendermint/abci/types" 9 | ) 10 | 11 | // NewQuerier creates a new querier for instance clients. 12 | func NewQuerier(k Keeper) sdk.Querier { 13 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { 14 | switch path[0] { 15 | case types.QueryGet: 16 | return get(ctx, path[1:], k) 17 | case types.QueryList: 18 | return list(ctx, k) 19 | default: 20 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown instance query endpoint") 21 | } 22 | } 23 | } 24 | 25 | func get(ctx sdk.Context, path []string, k Keeper) ([]byte, error) { 26 | if len(path) == 0 { 27 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing hash") 28 | } 29 | hash, err := hash.Decode(path[0]) 30 | if err != nil { 31 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 32 | } 33 | 34 | instance, err := k.Get(ctx, hash) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | res, err := types.ModuleCdc.MarshalJSON(instance) 40 | if err != nil { 41 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 42 | } 43 | return res, nil 44 | } 45 | 46 | func list(ctx sdk.Context, k Keeper) ([]byte, error) { 47 | instances, err := k.List(ctx) 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | res, err := types.ModuleCdc.MarshalJSON(instances) 53 | if err != nil { 54 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 55 | } 56 | return res, nil 57 | } 58 | -------------------------------------------------------------------------------- /x/instance/internal/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // RegisterCodec registers concrete types on codec 8 | func RegisterCodec(cdc *codec.Codec) {} 9 | 10 | // ModuleCdc defines the module codec 11 | var ModuleCdc *codec.Codec 12 | 13 | func init() { 14 | ModuleCdc = codec.New() 15 | RegisterCodec(ModuleCdc) 16 | codec.RegisterCrypto(ModuleCdc) 17 | ModuleCdc.Seal() 18 | } 19 | -------------------------------------------------------------------------------- /x/instance/internal/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // module event types and attributes 4 | const ( 5 | EventType = "instance" 6 | 7 | AttributeKeyHash = "hash" 8 | AttributeKeyService = "service" 9 | 10 | AttributeActionCreated = "created" 11 | ) 12 | -------------------------------------------------------------------------------- /x/instance/internal/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/hash" 6 | servicepb "github.com/mesg-foundation/engine/service" 7 | ) 8 | 9 | // ServiceKeeper module interface. 10 | type ServiceKeeper interface { 11 | Get(ctx sdk.Context, hash hash.Hash) (*servicepb.Service, error) 12 | } 13 | -------------------------------------------------------------------------------- /x/instance/internal/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | "github.com/mesg-foundation/engine/instance" 8 | ) 9 | 10 | // GenesisState - all instance state that must be provided at genesis 11 | type GenesisState struct { 12 | Instances []*instance.Instance `json:"instances" yaml:"instances" validate:"dive"` 13 | } 14 | 15 | // NewGenesisState creates a new GenesisState object 16 | func NewGenesisState(instances []*instance.Instance) GenesisState { 17 | return GenesisState{ 18 | Instances: instances, 19 | } 20 | } 21 | 22 | // DefaultGenesisState is the default GenesisState 23 | func DefaultGenesisState() GenesisState { 24 | return GenesisState{ 25 | Instances: []*instance.Instance{}, 26 | } 27 | } 28 | 29 | // ValidateGenesis validates the instance genesis parameters 30 | func ValidateGenesis(data GenesisState) error { 31 | if err := xvalidator.Struct(data); err != nil { 32 | return fmt.Errorf("failed to validate %s genesis state: %w", ModuleName, err) 33 | } 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /x/instance/internal/types/key.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the module 5 | ModuleName = "instance" 6 | 7 | // StoreKey to be used when creating the KVStore 8 | StoreKey = ModuleName 9 | 10 | // RouterKey to be used for routing msgs 11 | RouterKey = ModuleName 12 | 13 | // QuerierRoute to be used for routing 14 | QuerierRoute = ModuleName 15 | ) 16 | -------------------------------------------------------------------------------- /x/instance/internal/types/querier.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Query endpoints supported by the instance querier 4 | const ( 5 | QueryGet = "get" 6 | QueryList = "list" 7 | ) 8 | -------------------------------------------------------------------------------- /x/ownership/abci.go: -------------------------------------------------------------------------------- 1 | package ownership 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // BeginBlocker check for infraction evidence or downtime of validators 9 | // on every begin block 10 | func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {} 11 | 12 | // EndBlocker called every block, process inflation, update validator set. 13 | func EndBlocker(ctx sdk.Context, k Keeper) {} 14 | -------------------------------------------------------------------------------- /x/ownership/alias.go: -------------------------------------------------------------------------------- 1 | package ownership 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/x/ownership/internal/keeper" 5 | "github.com/mesg-foundation/engine/x/ownership/internal/types" 6 | ) 7 | 8 | // const aliases 9 | const ( 10 | ModuleName = types.ModuleName 11 | RouterKey = types.RouterKey 12 | StoreKey = types.StoreKey 13 | QuerierRoute = types.QuerierRoute 14 | ) 15 | 16 | // functions and variable aliases 17 | var ( 18 | NewKeeper = keeper.NewKeeper 19 | NewQuerier = keeper.NewQuerier 20 | RegisterCodec = types.RegisterCodec 21 | NewGenesisState = types.NewGenesisState 22 | DefaultGenesisState = types.DefaultGenesisState 23 | ValidateGenesis = types.ValidateGenesis 24 | 25 | ModuleCdc = types.ModuleCdc 26 | QueryList = types.QueryList 27 | 28 | EventType = types.EventType 29 | AttributeKeyHash = types.AttributeKeyHash 30 | AttributeKeyResourceHash = types.AttributeKeyResourceHash 31 | AttributeKeyResourceType = types.AttributeKeyResourceType 32 | AttributeKeyResourceAddress = types.AttributeKeyResourceAddress 33 | AttributeActionCreated = types.AttributeActionCreated 34 | AttributeActionDeleted = types.AttributeActionDeleted 35 | ) 36 | 37 | // module types 38 | type ( 39 | Keeper = keeper.Keeper 40 | GenesisState = types.GenesisState 41 | 42 | MsgWithdraw = types.MsgWithdraw 43 | ) 44 | -------------------------------------------------------------------------------- /x/ownership/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/context" 8 | "github.com/cosmos/cosmos-sdk/client/flags" 9 | "github.com/cosmos/cosmos-sdk/codec" 10 | "github.com/mesg-foundation/engine/ownership" 11 | "github.com/mesg-foundation/engine/x/ownership/internal/types" 12 | "github.com/spf13/cobra" 13 | ) 14 | 15 | // GetQueryCmd returns the cli query commands for this module 16 | func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { 17 | // Group ownership queries under a subcommand 18 | ownershipQueryCmd := &cobra.Command{ 19 | Use: types.ModuleName, 20 | Short: fmt.Sprintf("Query commands for the %s module", types.ModuleName), 21 | DisableFlagParsing: true, 22 | SuggestionsMinimumDistance: 2, 23 | RunE: client.ValidateCmd, 24 | } 25 | 26 | ownershipQueryCmd.AddCommand( 27 | flags.GetCommands( 28 | GetCmdList(queryRoute, cdc), 29 | )..., 30 | ) 31 | 32 | return ownershipQueryCmd 33 | } 34 | 35 | // GetCmdList returns command listing ownerships 36 | func GetCmdList(queryRoute string, cdc *codec.Codec) *cobra.Command { 37 | return &cobra.Command{ 38 | Use: "list", 39 | Short: "Query all the ownership", 40 | Args: cobra.NoArgs, 41 | RunE: func(cmd *cobra.Command, args []string) error { 42 | cliCtx := context.NewCLIContext().WithCodec(cdc) 43 | res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryList), nil) 44 | if err != nil { 45 | fmt.Printf("could not get ownerships\n%s\n", err.Error()) 46 | return nil 47 | } 48 | 49 | var out []*ownership.Ownership 50 | cdc.MustUnmarshalJSON(res, &out) 51 | return cliCtx.PrintOutput(out) 52 | }, 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /x/ownership/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | "github.com/cosmos/cosmos-sdk/client/context" 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | "github.com/cosmos/cosmos-sdk/codec" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | "github.com/cosmos/cosmos-sdk/x/auth" 14 | "github.com/cosmos/cosmos-sdk/x/auth/client/utils" 15 | "github.com/mesg-foundation/engine/hash" 16 | "github.com/mesg-foundation/engine/x/ownership/internal/types" 17 | "github.com/spf13/cobra" 18 | ) 19 | 20 | // GetTxCmd returns the transaction commands for this module 21 | func GetTxCmd(cdc *codec.Codec) *cobra.Command { 22 | ownershipTxCmd := &cobra.Command{ 23 | Use: types.ModuleName, 24 | Short: fmt.Sprintf("%s transactions subcommands", strings.Title(types.ModuleName)), 25 | DisableFlagParsing: true, 26 | SuggestionsMinimumDistance: 2, 27 | RunE: client.ValidateCmd, 28 | } 29 | 30 | ownershipTxCmd.AddCommand(flags.PostCommands( 31 | GetCmdWithdraw(cdc), 32 | )...) 33 | return ownershipTxCmd 34 | } 35 | 36 | // GetCmdWithdraw is the CLI command for sending a Withdraw transaction 37 | func GetCmdWithdraw(cdc *codec.Codec) *cobra.Command { 38 | return &cobra.Command{ 39 | Use: "withdraw-coins [resourceHash] [amount]", 40 | Short: "Withdraw coins from a resource", 41 | Args: cobra.ExactArgs(2), 42 | RunE: func(cmd *cobra.Command, args []string) error { 43 | inBuf := bufio.NewReader(cmd.InOrStdin()) 44 | cliCtx := context.NewCLIContext().WithCodec(cdc) 45 | 46 | txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 47 | 48 | resourceHash, err := hash.Decode(args[0]) 49 | if err != nil { 50 | return err 51 | } 52 | 53 | msg := types.MsgWithdraw{ 54 | Owner: cliCtx.GetFromAddress(), 55 | ResourceHash: resourceHash, 56 | Amount: args[1], 57 | } 58 | if err := msg.ValidateBasic(); err != nil { 59 | return err 60 | } 61 | 62 | return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) 63 | }, 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /x/ownership/client/rest/query.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/cosmos/cosmos-sdk/client/context" 8 | "github.com/cosmos/cosmos-sdk/types/rest" 9 | "github.com/gorilla/mux" 10 | "github.com/mesg-foundation/engine/x/ownership/internal/types" 11 | ) 12 | 13 | func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) { 14 | r.HandleFunc( 15 | "/ownership/list", 16 | queryListHandlerFn(cliCtx), 17 | ).Methods(http.MethodGet) 18 | } 19 | 20 | func queryListHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { 21 | return func(w http.ResponseWriter, r *http.Request) { 22 | cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) 23 | if !ok { 24 | return 25 | } 26 | 27 | route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryList) 28 | res, height, err := cliCtx.QueryWithData(route, nil) 29 | if err != nil { 30 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 31 | return 32 | } 33 | 34 | cliCtx = cliCtx.WithHeight(height) 35 | rest.PostProcessResponse(w, cliCtx, res) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /x/ownership/client/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | // RegisterRoutes registers ownership-related REST handlers to a router 9 | func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { 10 | registerQueryRoutes(cliCtx, r) 11 | registerTxRoutes(cliCtx, r) 12 | } 13 | -------------------------------------------------------------------------------- /x/ownership/client/rest/tx.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/cosmos/cosmos-sdk/client/context" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/cosmos/cosmos-sdk/types/rest" 9 | "github.com/cosmos/cosmos-sdk/x/auth/client/utils" 10 | "github.com/gorilla/mux" 11 | "github.com/mesg-foundation/engine/hash" 12 | "github.com/mesg-foundation/engine/x/ownership/internal/types" 13 | ) 14 | 15 | type withdrawReq struct { 16 | BaseReq rest.BaseReq `json:"base_req"` 17 | Amount string `json:"amount"` 18 | Hash hash.Hash `json:"hash"` 19 | } 20 | 21 | func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { 22 | r.HandleFunc( 23 | "/ownership/withdraw-coins", 24 | txWithdrawHandlerFn(cliCtx), 25 | ).Methods(http.MethodPost) 26 | } 27 | 28 | func txWithdrawHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { 29 | return func(w http.ResponseWriter, r *http.Request) { 30 | var req withdrawReq 31 | 32 | if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { 33 | rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") 34 | return 35 | } 36 | 37 | baseReq := req.BaseReq.Sanitize() 38 | if !baseReq.ValidateBasic(w) { 39 | return 40 | } 41 | 42 | owner, err := sdk.AccAddressFromBech32(baseReq.From) 43 | if err != nil { 44 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 45 | return 46 | } 47 | 48 | msg := types.MsgWithdraw{ 49 | Owner: owner, 50 | ResourceHash: req.Hash, 51 | Amount: req.Amount, 52 | } 53 | if err := msg.ValidateBasic(); err != nil { 54 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 55 | return 56 | } 57 | 58 | utils.WriteGenerateStdTxResponse(w, cliCtx, baseReq, []sdk.Msg{msg}) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /x/ownership/genesis.go: -------------------------------------------------------------------------------- 1 | package ownership 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/x/ownership/internal/types" 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | ) 8 | 9 | // InitGenesis initialize default parameters and the keeper's address to pubkey map. 10 | func InitGenesis(ctx sdk.Context, k Keeper, data types.GenesisState) []abci.ValidatorUpdate { 11 | if err := k.Import(ctx, data.Ownerships); err != nil { 12 | panic(err) 13 | } 14 | return []abci.ValidatorUpdate{} 15 | } 16 | 17 | // ExportGenesis writes the current store values // to a genesis file, 18 | // which can be imported again with InitGenesis. 19 | func ExportGenesis(ctx sdk.Context, k Keeper) types.GenesisState { 20 | ownerships, err := k.List(ctx) 21 | if err != nil { 22 | panic(err) 23 | } 24 | return types.NewGenesisState(ownerships) 25 | } 26 | -------------------------------------------------------------------------------- /x/ownership/handler.go: -------------------------------------------------------------------------------- 1 | package ownership 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 8 | "github.com/mesg-foundation/engine/x/ownership/internal/types" 9 | ) 10 | 11 | // NewHandler creates an sdk.Handler for all the instance type messages 12 | func NewHandler(k Keeper) sdk.Handler { 13 | return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 14 | ctx = ctx.WithEventManager(sdk.NewEventManager()) 15 | switch msg := msg.(type) { 16 | case MsgWithdraw: 17 | return handleMsgWithdraw(ctx, k, msg) 18 | default: 19 | errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) 20 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) 21 | } 22 | } 23 | } 24 | 25 | // handleMsgWithdraw withdraws coins from resource to the owner. 26 | func handleMsgWithdraw(ctx sdk.Context, k Keeper, msg MsgWithdraw) (*sdk.Result, error) { 27 | if err := k.Withdraw(ctx, msg); err != nil { 28 | return nil, err 29 | } 30 | 31 | ctx.EventManager().EmitEvent( 32 | sdk.NewEvent( 33 | sdk.EventTypeMessage, 34 | sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), 35 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Owner.String()), 36 | ), 37 | ) 38 | 39 | return &sdk.Result{ 40 | Events: ctx.EventManager().Events(), 41 | }, nil 42 | } 43 | -------------------------------------------------------------------------------- /x/ownership/internal/keeper/querier.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/x/ownership/internal/types" 7 | abci "github.com/tendermint/tendermint/abci/types" 8 | ) 9 | 10 | // NewQuerier creates a new querier for ownership clients. 11 | func NewQuerier(k Keeper) sdk.Querier { 12 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { 13 | switch path[0] { 14 | case types.QueryList: 15 | return list(ctx, k) 16 | default: 17 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown ownership query endpoint") 18 | } 19 | } 20 | } 21 | 22 | func list(ctx sdk.Context, k Keeper) ([]byte, error) { 23 | ownerships, err := k.List(ctx) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | res, err := types.ModuleCdc.MarshalJSON(ownerships) 29 | if err != nil { 30 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 31 | } 32 | return res, nil 33 | } 34 | -------------------------------------------------------------------------------- /x/ownership/internal/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // RegisterCodec registers concrete types on codec. 8 | func RegisterCodec(cdc *codec.Codec) { 9 | cdc.RegisterConcrete(MsgWithdraw{}, "ownership/withdraw", nil) 10 | } 11 | 12 | // ModuleCdc defines the module codec. 13 | var ModuleCdc *codec.Codec 14 | 15 | func init() { 16 | ModuleCdc = codec.New() 17 | RegisterCodec(ModuleCdc) 18 | codec.RegisterCrypto(ModuleCdc) 19 | ModuleCdc.Seal() 20 | } 21 | -------------------------------------------------------------------------------- /x/ownership/internal/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // module event types and attributes 4 | const ( 5 | EventType = "ownership" 6 | 7 | AttributeKeyHash = "hash" 8 | AttributeKeyResourceHash = "resource_hash" 9 | AttributeKeyResourceType = "ressource_type" 10 | AttributeKeyResourceAddress = "ressource_address" 11 | 12 | AttributeActionCreated = "created" 13 | AttributeActionDeleted = "deleted" 14 | ) 15 | -------------------------------------------------------------------------------- /x/ownership/internal/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | // BankKeeper module interface. 8 | type BankKeeper interface { 9 | SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error 10 | GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins 11 | } 12 | -------------------------------------------------------------------------------- /x/ownership/internal/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | fmt "fmt" 5 | 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | "github.com/mesg-foundation/engine/ownership" 8 | ) 9 | 10 | // GenesisState - all ownership state that must be provided at genesis 11 | type GenesisState struct { 12 | Ownerships []*ownership.Ownership `json:"ownerships" yaml:"ownerships" validate:"dive"` 13 | } 14 | 15 | // NewGenesisState creates a new GenesisState object 16 | func NewGenesisState(ownerships []*ownership.Ownership) GenesisState { 17 | return GenesisState{ 18 | Ownerships: ownerships, 19 | } 20 | } 21 | 22 | // DefaultGenesisState is the default GenesisState 23 | func DefaultGenesisState() GenesisState { 24 | return GenesisState{ 25 | Ownerships: []*ownership.Ownership{}, 26 | } 27 | } 28 | 29 | // ValidateGenesis validates the ownership genesis parameters 30 | func ValidateGenesis(data GenesisState) error { 31 | if err := xvalidator.Struct(data); err != nil { 32 | return fmt.Errorf("failed to validate %s genesis state: %w", ModuleName, err) 33 | } 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /x/ownership/internal/types/key.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the module 5 | ModuleName = "ownership" 6 | 7 | // StoreKey to be used when creating the KVStore 8 | StoreKey = ModuleName 9 | 10 | // RouterKey to be used for routing msgs 11 | RouterKey = ModuleName 12 | 13 | // QuerierRoute to be used for routing 14 | QuerierRoute = ModuleName 15 | ) 16 | -------------------------------------------------------------------------------- /x/ownership/internal/types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | ) 8 | 9 | // Route should return the name of the module. 10 | func (msg MsgWithdraw) Route() string { 11 | return ModuleName 12 | } 13 | 14 | // Type returns the action. 15 | func (msg MsgWithdraw) Type() string { 16 | return "withdraw" 17 | } 18 | 19 | // ValidateBasic runs stateless checks on the message. 20 | func (msg MsgWithdraw) ValidateBasic() error { 21 | if err := xvalidator.Struct(msg); err != nil { 22 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 23 | } 24 | return nil 25 | } 26 | 27 | // GetSignBytes encodes the message for signing. 28 | func (msg MsgWithdraw) GetSignBytes() []byte { 29 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 30 | } 31 | 32 | // GetSigners defines whose signature is required. 33 | func (msg MsgWithdraw) GetSigners() []sdk.AccAddress { 34 | return []sdk.AccAddress{msg.Owner} 35 | } 36 | -------------------------------------------------------------------------------- /x/ownership/internal/types/msg.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | 5 | package mesg.ownership.types; 6 | option go_package = "github.com/mesg-foundation/engine/x/ownership/internal/types"; 7 | 8 | // The message to withdraw coins from an ownership. 9 | message MsgWithdraw { 10 | // The ownership's owner. 11 | bytes owner = 1 [ 12 | (gogoproto.moretags) = 'validate:"required,accaddress"', 13 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 14 | ]; 15 | 16 | // Hash of the resource to withdraw from. 17 | bytes resourceHash = 2 [ 18 | (gogoproto.moretags) = 'validate:"required,hash"', 19 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 20 | ]; 21 | 22 | // amount to withdraw 23 | string amount = 3 [ 24 | (gogoproto.moretags) = 'validate:"required,coinsPositiveZero"' 25 | ]; 26 | } 27 | -------------------------------------------------------------------------------- /x/ownership/internal/types/querier.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Query endpoints supported by the ownership querier 4 | const ( 5 | QueryList = "list" 6 | ) 7 | -------------------------------------------------------------------------------- /x/process/abci.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // BeginBlocker check for infraction evidence or downtime of validators 9 | // on every begin block 10 | func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {} 11 | 12 | // EndBlocker called every block, process inflation, update validator set. 13 | func EndBlocker(ctx sdk.Context, k Keeper) {} 14 | -------------------------------------------------------------------------------- /x/process/alias.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/x/process/internal/keeper" 5 | "github.com/mesg-foundation/engine/x/process/internal/types" 6 | ) 7 | 8 | // const aliases 9 | const ( 10 | ModuleName = types.ModuleName 11 | RouterKey = types.RouterKey 12 | StoreKey = types.StoreKey 13 | QuerierRoute = types.QuerierRoute 14 | ) 15 | 16 | // functions and variable aliases 17 | var ( 18 | NewKeeper = keeper.NewKeeper 19 | NewQuerier = keeper.NewQuerier 20 | RegisterCodec = types.RegisterCodec 21 | NewGenesisState = types.NewGenesisState 22 | DefaultGenesisState = types.DefaultGenesisState 23 | ValidateGenesis = types.ValidateGenesis 24 | 25 | ModuleCdc = types.ModuleCdc 26 | 27 | QueryGet = types.QueryGet 28 | QueryList = types.QueryList 29 | QueryExist = types.QueryExist 30 | 31 | EventType = types.EventType 32 | AttributeKeyHash = types.AttributeKeyHash 33 | AttributeKeyAddress = types.AttributeKeyAddress 34 | AttributeActionCreated = types.AttributeActionCreated 35 | AttributeActionDeleted = types.AttributeActionDeleted 36 | ) 37 | 38 | // module types 39 | type ( 40 | Keeper = keeper.Keeper 41 | GenesisState = types.GenesisState 42 | 43 | MsgCreate = types.MsgCreate 44 | MsgDelete = types.MsgDelete 45 | ) 46 | -------------------------------------------------------------------------------- /x/process/client/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gorilla/mux" 5 | 6 | "github.com/cosmos/cosmos-sdk/client/context" 7 | ) 8 | 9 | // RegisterRoutes registers process-related REST handlers to a router 10 | func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { 11 | registerQueryRoutes(cliCtx, r) 12 | registerTxRoutes(cliCtx, r) 13 | } 14 | -------------------------------------------------------------------------------- /x/process/client/rest/tx.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { 9 | // TODO: 10 | } 11 | -------------------------------------------------------------------------------- /x/process/genesis.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/x/process/internal/types" 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | ) 8 | 9 | // InitGenesis initialize default parameters and the keeper's address to pubkey map. 10 | func InitGenesis(ctx sdk.Context, k Keeper, data types.GenesisState) []abci.ValidatorUpdate { 11 | if err := k.Import(ctx, data.Processes); err != nil { 12 | panic(err) 13 | } 14 | return []abci.ValidatorUpdate{} 15 | } 16 | 17 | // ExportGenesis writes the current store values // to a genesis file, 18 | // which can be imported again with InitGenesis. 19 | func ExportGenesis(ctx sdk.Context, k Keeper) types.GenesisState { 20 | processes, err := k.List(ctx) 21 | if err != nil { 22 | panic(err) 23 | } 24 | return types.NewGenesisState(processes) 25 | } 26 | -------------------------------------------------------------------------------- /x/process/handler.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/x/process/internal/types" 7 | ) 8 | 9 | // NewHandler creates an sdk.Handler for all the process type messages 10 | func NewHandler(k Keeper) sdk.Handler { 11 | return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 12 | ctx = ctx.WithEventManager(sdk.NewEventManager()) 13 | switch msg := msg.(type) { 14 | case MsgCreate: 15 | return handleMsgCreate(ctx, k, &msg) 16 | case MsgDelete: 17 | return handleMsgDelete(ctx, k, &msg) 18 | default: 19 | return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg) 20 | } 21 | } 22 | } 23 | 24 | // handleMsgCreate creates a new process. 25 | func handleMsgCreate(ctx sdk.Context, k Keeper, msg *MsgCreate) (*sdk.Result, error) { 26 | p, err := k.Create(ctx, msg) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | ctx.EventManager().EmitEvent( 32 | sdk.NewEvent( 33 | sdk.EventTypeMessage, 34 | sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), 35 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Owner.String()), 36 | ), 37 | ) 38 | 39 | return &sdk.Result{ 40 | Data: p.Hash, 41 | Events: ctx.EventManager().Events(), 42 | }, nil 43 | } 44 | 45 | // handleMsgDelete deletes a process. 46 | func handleMsgDelete(ctx sdk.Context, k Keeper, msg *MsgDelete) (*sdk.Result, error) { 47 | if err := k.Delete(ctx, msg); err != nil { 48 | return nil, err 49 | } 50 | 51 | ctx.EventManager().EmitEvent( 52 | sdk.NewEvent( 53 | sdk.EventTypeMessage, 54 | sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), 55 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Owner.String()), 56 | ), 57 | ) 58 | 59 | return &sdk.Result{Events: ctx.EventManager().Events()}, nil 60 | } 61 | -------------------------------------------------------------------------------- /x/process/internal/keeper/querier.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/hash" 7 | "github.com/mesg-foundation/engine/x/process/internal/types" 8 | abci "github.com/tendermint/tendermint/abci/types" 9 | ) 10 | 11 | // NewQuerier creates a new querier for instance clients. 12 | func NewQuerier(k Keeper) sdk.Querier { 13 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { 14 | switch path[0] { 15 | case types.QueryGet: 16 | return get(ctx, path[1:], k) 17 | case types.QueryList: 18 | return list(ctx, k) 19 | case types.QueryExist: 20 | return exist(ctx, k, path[1:]) 21 | default: 22 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown process query endpoint") 23 | } 24 | } 25 | } 26 | 27 | func get(ctx sdk.Context, path []string, k Keeper) ([]byte, error) { 28 | if len(path) == 0 { 29 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing hash") 30 | } 31 | hash, err := hash.Decode(path[0]) 32 | if err != nil { 33 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 34 | } 35 | 36 | instance, err := k.Get(ctx, hash) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | res, err := types.ModuleCdc.MarshalJSON(instance) 42 | if err != nil { 43 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 44 | } 45 | return res, nil 46 | } 47 | 48 | func list(ctx sdk.Context, k Keeper) ([]byte, error) { 49 | instances, err := k.List(ctx) 50 | if err != nil { 51 | return nil, err 52 | } 53 | 54 | res, err := types.ModuleCdc.MarshalJSON(instances) 55 | if err != nil { 56 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 57 | } 58 | return res, nil 59 | } 60 | 61 | func exist(ctx sdk.Context, k Keeper, path []string) ([]byte, error) { 62 | if len(path) == 0 { 63 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing hash") 64 | } 65 | hash, err := hash.Decode(path[0]) 66 | if err != nil { 67 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 68 | } 69 | 70 | exists, err := k.Exists(ctx, hash) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | res, err := types.ModuleCdc.MarshalJSON(exists) 76 | if err != nil { 77 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 78 | } 79 | return res, nil 80 | } 81 | -------------------------------------------------------------------------------- /x/process/internal/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | processpb "github.com/mesg-foundation/engine/process" 6 | "github.com/mesg-foundation/engine/protobuf/types" 7 | ) 8 | 9 | // RegisterCodec registers concrete types on codec 10 | func RegisterCodec(cdc *codec.Codec) { 11 | processpb.RegisterCodec(cdc) 12 | cdc.RegisterConcrete(MsgCreate{}, "process/create", nil) 13 | cdc.RegisterConcrete(MsgDelete{}, "process/delete", nil) 14 | } 15 | 16 | // ModuleCdc defines the module codec 17 | var ModuleCdc *codec.Codec 18 | 19 | func init() { 20 | ModuleCdc = codec.New() 21 | RegisterCodec(ModuleCdc) 22 | codec.RegisterCrypto(ModuleCdc) 23 | types.RegisterCodec(ModuleCdc) 24 | ModuleCdc.Seal() 25 | } 26 | -------------------------------------------------------------------------------- /x/process/internal/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // module event types and attributes 4 | const ( 5 | EventType = "process" 6 | 7 | AttributeKeyHash = "hash" 8 | AttributeKeyAddress = "address" 9 | 10 | AttributeActionCreated = "created" 11 | AttributeActionDeleted = "deleted" 12 | ) 13 | -------------------------------------------------------------------------------- /x/process/internal/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/hash" 6 | instancepb "github.com/mesg-foundation/engine/instance" 7 | ownershippb "github.com/mesg-foundation/engine/ownership" 8 | ) 9 | 10 | // InstanceKeeper module interface. 11 | type InstanceKeeper interface { 12 | Get(ctx sdk.Context, instanceHash hash.Hash) (*instancepb.Instance, error) 13 | } 14 | 15 | // OwnershipKeeper module interface. 16 | type OwnershipKeeper interface { 17 | Delete(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash.Hash) error 18 | Set(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash.Hash, resource ownershippb.Ownership_Resource, resourceAddress sdk.AccAddress) (*ownershippb.Ownership, error) 19 | } 20 | -------------------------------------------------------------------------------- /x/process/internal/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | fmt "fmt" 5 | 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | "github.com/mesg-foundation/engine/process" 8 | ) 9 | 10 | // GenesisState - all instance state that must be provided at genesis 11 | type GenesisState struct { 12 | Processes []*process.Process `json:"processes" yaml:"processes" validate:"dive"` 13 | } 14 | 15 | // NewGenesisState creates a new GenesisState object 16 | func NewGenesisState(processes []*process.Process) GenesisState { 17 | return GenesisState{ 18 | Processes: processes, 19 | } 20 | } 21 | 22 | // DefaultGenesisState is the default GenesisState 23 | func DefaultGenesisState() GenesisState { 24 | return GenesisState{ 25 | Processes: []*process.Process{}, 26 | } 27 | } 28 | 29 | // ValidateGenesis validates the instance genesis parameters 30 | func ValidateGenesis(data GenesisState) error { 31 | if err := xvalidator.Struct(data); err != nil { 32 | return fmt.Errorf("failed to validate %s genesis state: %w", ModuleName, err) 33 | } 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /x/process/internal/types/key.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the module 5 | ModuleName = "process" 6 | 7 | // StoreKey to be used when creating the KVStore 8 | StoreKey = ModuleName 9 | 10 | // RouterKey to be used for routing msgs 11 | RouterKey = ModuleName 12 | 13 | // QuerierRoute to be used for routing 14 | QuerierRoute = ModuleName 15 | ) 16 | -------------------------------------------------------------------------------- /x/process/internal/types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | processpb "github.com/mesg-foundation/engine/process" 8 | ) 9 | 10 | // Route should return the name of the module route. 11 | func (msg MsgCreate) Route() string { 12 | return RouterKey 13 | } 14 | 15 | // Type returns the action. 16 | func (msg MsgCreate) Type() string { 17 | return "create" 18 | } 19 | 20 | // ValidateBasic runs stateless checks on the message. 21 | func (msg MsgCreate) ValidateBasic() error { 22 | if err := xvalidator.Struct(msg); err != nil { 23 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 24 | } 25 | if _, err := processpb.New(msg.Name, msg.Nodes, msg.Edges, msg.Owner); err != nil { 26 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 27 | } 28 | return nil 29 | } 30 | 31 | // GetSignBytes encodes the message for signing. 32 | func (msg MsgCreate) GetSignBytes() []byte { 33 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 34 | } 35 | 36 | // GetSigners defines whose signature is required. 37 | func (msg MsgCreate) GetSigners() []sdk.AccAddress { 38 | return []sdk.AccAddress{msg.Owner} 39 | } 40 | 41 | // Route should return the name of the module. 42 | func (msg MsgDelete) Route() string { 43 | return ModuleName 44 | } 45 | 46 | // Type returns the action. 47 | func (msg MsgDelete) Type() string { 48 | return "delete" 49 | } 50 | 51 | // ValidateBasic runs stateless checks on the message. 52 | func (msg MsgDelete) ValidateBasic() error { 53 | if err := xvalidator.Struct(msg); err != nil { 54 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 55 | } 56 | return nil 57 | } 58 | 59 | // GetSignBytes encodes the message for signing. 60 | func (msg MsgDelete) GetSignBytes() []byte { 61 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 62 | } 63 | 64 | // GetSigners defines whose signature is required. 65 | func (msg MsgDelete) GetSigners() []sdk.AccAddress { 66 | return []sdk.AccAddress{msg.Owner} 67 | } 68 | -------------------------------------------------------------------------------- /x/process/internal/types/msg.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | import "protobuf/types/process.proto"; 5 | 6 | package mesg.process.types; 7 | option go_package = "github.com/mesg-foundation/engine/x/process/internal/types"; 8 | 9 | // The message to create a Process. 10 | message MsgCreate { 11 | // Process's name 12 | string name = 1 [ 13 | (gogoproto.moretags) = 'validate:"required,printascii"' 14 | ]; 15 | 16 | // List of nodes of the process. 17 | repeated mesg.types.Process.Node nodes = 2 [ 18 | (gogoproto.moretags) = 'validate:"dive"' 19 | ]; 20 | 21 | // List of edges of the process. 22 | repeated mesg.types.Process.Edge edges = 3 [ 23 | (gogoproto.moretags) = 'validate:"dive"' 24 | ]; 25 | 26 | // The process's owner. 27 | bytes owner = 4 [ 28 | (gogoproto.moretags) = 'validate:"required,accaddress"', 29 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 30 | ]; 31 | } 32 | 33 | // The message to delete a Process. 34 | message MsgDelete { 35 | // The process's hash to delete. 36 | bytes hash = 1 [ 37 | (gogoproto.moretags) = 'validate:"required,hash"', 38 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 39 | ]; 40 | 41 | // The process's owner. 42 | bytes owner = 2 [ 43 | (gogoproto.moretags) = 'validate:"required,accaddress"', 44 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 45 | ]; 46 | } 47 | -------------------------------------------------------------------------------- /x/process/internal/types/querier.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Query endpoints supported by the process querier 4 | const ( 5 | QueryGet = "get" 6 | QueryList = "list" 7 | QueryExist = "exist" 8 | ) 9 | -------------------------------------------------------------------------------- /x/runner/abci.go: -------------------------------------------------------------------------------- 1 | package runner 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // BeginBlocker check for infraction evidence or downtime of validators 9 | // on every begin block 10 | func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {} 11 | 12 | // EndBlocker called every block, process inflation, update validator set. 13 | func EndBlocker(ctx sdk.Context, k Keeper) {} 14 | -------------------------------------------------------------------------------- /x/runner/alias.go: -------------------------------------------------------------------------------- 1 | package runner 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/x/runner/internal/keeper" 5 | "github.com/mesg-foundation/engine/x/runner/internal/types" 6 | ) 7 | 8 | // const aliases 9 | const ( 10 | ModuleName = types.ModuleName 11 | RouterKey = types.RouterKey 12 | StoreKey = types.StoreKey 13 | QuerierRoute = types.QuerierRoute 14 | ) 15 | 16 | // functions and variable aliases 17 | var ( 18 | NewKeeper = keeper.NewKeeper 19 | NewQuerier = keeper.NewQuerier 20 | RegisterCodec = types.RegisterCodec 21 | NewGenesisState = types.NewGenesisState 22 | DefaultGenesisState = types.DefaultGenesisState 23 | ValidateGenesis = types.ValidateGenesis 24 | 25 | ModuleCdc = types.ModuleCdc 26 | 27 | QueryGet = types.QueryGet 28 | QueryList = types.QueryList 29 | QueryExist = types.QueryExist 30 | 31 | EventType = types.EventType 32 | AttributeKeyHash = types.AttributeKeyHash 33 | AttributeKeyAddress = types.AttributeKeyAddress 34 | AttributeKeyInstance = types.AttributeKeyInstance 35 | AttributeActionCreated = types.AttributeActionCreated 36 | AttributeActionDeleted = types.AttributeActionDeleted 37 | ) 38 | 39 | // module types 40 | type ( 41 | Keeper = keeper.Keeper 42 | GenesisState = types.GenesisState 43 | 44 | MsgCreate = types.MsgCreate 45 | MsgDelete = types.MsgDelete 46 | ) 47 | -------------------------------------------------------------------------------- /x/runner/client/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gorilla/mux" 5 | 6 | "github.com/cosmos/cosmos-sdk/client/context" 7 | ) 8 | 9 | // RegisterRoutes registers runner-related REST handlers to a router 10 | func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { 11 | registerQueryRoutes(cliCtx, r) 12 | registerTxRoutes(cliCtx, r) 13 | } 14 | -------------------------------------------------------------------------------- /x/runner/client/rest/tx.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { 9 | // TODO: 10 | } 11 | -------------------------------------------------------------------------------- /x/runner/genesis.go: -------------------------------------------------------------------------------- 1 | package runner 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/x/runner/internal/types" 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | ) 8 | 9 | // InitGenesis initialize default parameters and the keeper's address to pubkey map. 10 | func InitGenesis(ctx sdk.Context, k Keeper, data types.GenesisState) []abci.ValidatorUpdate { 11 | if err := k.Import(ctx, data.Runners); err != nil { 12 | panic(err) 13 | } 14 | return []abci.ValidatorUpdate{} 15 | } 16 | 17 | // ExportGenesis writes the current store values // to a genesis file, 18 | // which can be imported again with InitGenesis. 19 | func ExportGenesis(ctx sdk.Context, k Keeper) types.GenesisState { 20 | runners, err := k.List(ctx) 21 | if err != nil { 22 | panic(err) 23 | } 24 | return types.NewGenesisState(runners) 25 | } 26 | -------------------------------------------------------------------------------- /x/runner/handler.go: -------------------------------------------------------------------------------- 1 | package runner 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/x/runner/internal/types" 7 | ) 8 | 9 | // NewHandler creates an sdk.Handler for all the runner type messages 10 | func NewHandler(k Keeper) sdk.Handler { 11 | return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 12 | ctx = ctx.WithEventManager(sdk.NewEventManager()) 13 | switch msg := msg.(type) { 14 | case MsgCreate: 15 | return handleMsgCreate(ctx, k, &msg) 16 | case MsgDelete: 17 | return handleMsgDelete(ctx, k, &msg) 18 | default: 19 | return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg) 20 | } 21 | } 22 | } 23 | 24 | // handleMsgCreate creates a new runner. 25 | func handleMsgCreate(ctx sdk.Context, k Keeper, msg *MsgCreate) (*sdk.Result, error) { 26 | run, err := k.Create(ctx, msg) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | ctx.EventManager().EmitEvent( 32 | sdk.NewEvent( 33 | sdk.EventTypeMessage, 34 | sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), 35 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Owner.String()), 36 | ), 37 | ) 38 | 39 | return &sdk.Result{ 40 | Data: run.Hash, 41 | Events: ctx.EventManager().Events(), 42 | }, nil 43 | } 44 | 45 | // handleMsgDelete deletes a runner. 46 | func handleMsgDelete(ctx sdk.Context, k Keeper, msg *MsgDelete) (*sdk.Result, error) { 47 | if err := k.Delete(ctx, msg); err != nil { 48 | return nil, err 49 | } 50 | 51 | ctx.EventManager().EmitEvent( 52 | sdk.NewEvent( 53 | sdk.EventTypeMessage, 54 | sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), 55 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Owner.String()), 56 | ), 57 | ) 58 | 59 | return &sdk.Result{Events: ctx.EventManager().Events()}, nil 60 | } 61 | -------------------------------------------------------------------------------- /x/runner/internal/keeper/querier.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/hash" 7 | "github.com/mesg-foundation/engine/x/runner/internal/types" 8 | abci "github.com/tendermint/tendermint/abci/types" 9 | ) 10 | 11 | // NewQuerier creates a new querier for instance clients. 12 | func NewQuerier(k Keeper) sdk.Querier { 13 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { 14 | switch path[0] { 15 | case types.QueryGet: 16 | return get(ctx, path[1:], k) 17 | case types.QueryList: 18 | return list(ctx, k) 19 | case types.QueryExist: 20 | return exist(ctx, k, path[1:]) 21 | default: 22 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown runner query endpoint") 23 | } 24 | } 25 | } 26 | 27 | func get(ctx sdk.Context, path []string, k Keeper) ([]byte, error) { 28 | if len(path) == 0 { 29 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing hash") 30 | } 31 | hash, err := hash.Decode(path[0]) 32 | if err != nil { 33 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 34 | } 35 | 36 | instance, err := k.Get(ctx, hash) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | res, err := types.ModuleCdc.MarshalJSON(instance) 42 | if err != nil { 43 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 44 | } 45 | return res, nil 46 | } 47 | 48 | func list(ctx sdk.Context, k Keeper) ([]byte, error) { 49 | instances, err := k.List(ctx) 50 | if err != nil { 51 | return nil, err 52 | } 53 | 54 | res, err := types.ModuleCdc.MarshalJSON(instances) 55 | if err != nil { 56 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 57 | } 58 | return res, nil 59 | } 60 | 61 | func exist(ctx sdk.Context, k Keeper, path []string) ([]byte, error) { 62 | if len(path) == 0 { 63 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing hash") 64 | } 65 | hash, err := hash.Decode(path[0]) 66 | if err != nil { 67 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 68 | } 69 | 70 | exists, err := k.Exists(ctx, hash) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | res, err := types.ModuleCdc.MarshalJSON(exists) 76 | if err != nil { 77 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 78 | } 79 | return res, nil 80 | } 81 | -------------------------------------------------------------------------------- /x/runner/internal/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // RegisterCodec registers concrete types on codec 8 | func RegisterCodec(cdc *codec.Codec) { 9 | cdc.RegisterConcrete(MsgCreate{}, "runner/create", nil) 10 | cdc.RegisterConcrete(MsgDelete{}, "runner/delete", nil) 11 | } 12 | 13 | // ModuleCdc defines the module codec 14 | var ModuleCdc *codec.Codec 15 | 16 | func init() { 17 | ModuleCdc = codec.New() 18 | RegisterCodec(ModuleCdc) 19 | codec.RegisterCrypto(ModuleCdc) 20 | ModuleCdc.Seal() 21 | } 22 | -------------------------------------------------------------------------------- /x/runner/internal/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // module event types and attributes 4 | const ( 5 | EventType = "runner" 6 | 7 | AttributeKeyHash = "hash" 8 | AttributeKeyAddress = "address" 9 | AttributeKeyInstance = "instance" 10 | 11 | AttributeActionCreated = "created" 12 | AttributeActionDeleted = "deleted" 13 | ) 14 | -------------------------------------------------------------------------------- /x/runner/internal/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/hash" 6 | "github.com/mesg-foundation/engine/instance" 7 | ownershippb "github.com/mesg-foundation/engine/ownership" 8 | ) 9 | 10 | // InstanceKeeper module interface. 11 | type InstanceKeeper interface { 12 | FetchOrCreate(ctx sdk.Context, serviceHash hash.Hash, envHash hash.Hash) (*instance.Instance, error) 13 | } 14 | 15 | // OwnershipKeeper module interface. 16 | type OwnershipKeeper interface { 17 | Set(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash.Hash, resource ownershippb.Ownership_Resource, resourceAddress sdk.AccAddress) (*ownershippb.Ownership, error) 18 | Delete(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash.Hash) error 19 | } 20 | -------------------------------------------------------------------------------- /x/runner/internal/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | fmt "fmt" 5 | 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | "github.com/mesg-foundation/engine/runner" 8 | ) 9 | 10 | // GenesisState - all instance state that must be provided at genesis 11 | type GenesisState struct { 12 | Runners []*runner.Runner `json:"runners" yaml:"runners" validate:"dive"` 13 | } 14 | 15 | // NewGenesisState creates a new GenesisState object 16 | func NewGenesisState(execs []*runner.Runner) GenesisState { 17 | return GenesisState{ 18 | Runners: execs, 19 | } 20 | } 21 | 22 | // DefaultGenesisState is the default GenesisState 23 | func DefaultGenesisState() GenesisState { 24 | return GenesisState{ 25 | Runners: []*runner.Runner{}, 26 | } 27 | } 28 | 29 | // ValidateGenesis validates the instance genesis parameters 30 | func ValidateGenesis(data GenesisState) error { 31 | if err := xvalidator.Struct(data); err != nil { 32 | return fmt.Errorf("failed to validate %s genesis state: %w", ModuleName, err) 33 | } 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /x/runner/internal/types/key.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the module 5 | ModuleName = "runner" 6 | 7 | // StoreKey to be used when creating the KVStore 8 | StoreKey = ModuleName 9 | 10 | // RouterKey to be used for routing msgs 11 | RouterKey = ModuleName 12 | 13 | // QuerierRoute to be used for routing 14 | QuerierRoute = ModuleName 15 | ) 16 | -------------------------------------------------------------------------------- /x/runner/internal/types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | ) 8 | 9 | // Route should return the name of the module route. 10 | func (msg MsgCreate) Route() string { 11 | return RouterKey 12 | } 13 | 14 | // Type returns the action. 15 | func (msg MsgCreate) Type() string { 16 | return "create" 17 | } 18 | 19 | // ValidateBasic runs stateless checks on the message. 20 | func (msg MsgCreate) ValidateBasic() error { 21 | if err := xvalidator.Struct(msg); err != nil { 22 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 23 | } 24 | return nil 25 | } 26 | 27 | // GetSignBytes encodes the message for signing. 28 | func (msg MsgCreate) GetSignBytes() []byte { 29 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 30 | } 31 | 32 | // GetSigners defines whose signature is required. 33 | func (msg MsgCreate) GetSigners() []sdk.AccAddress { 34 | return []sdk.AccAddress{msg.Owner} 35 | } 36 | 37 | // Route should return the name of the module. 38 | func (msg MsgDelete) Route() string { 39 | return ModuleName 40 | } 41 | 42 | // Type returns the action. 43 | func (msg MsgDelete) Type() string { 44 | return "delete" 45 | } 46 | 47 | // ValidateBasic runs stateless checks on the message. 48 | func (msg MsgDelete) ValidateBasic() error { 49 | if err := xvalidator.Struct(msg); err != nil { 50 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 51 | } 52 | return nil 53 | } 54 | 55 | // GetSignBytes encodes the message for signing. 56 | func (msg MsgDelete) GetSignBytes() []byte { 57 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 58 | } 59 | 60 | // GetSigners defines whose signature is required. 61 | func (msg MsgDelete) GetSigners() []sdk.AccAddress { 62 | return []sdk.AccAddress{msg.Owner} 63 | } 64 | -------------------------------------------------------------------------------- /x/runner/internal/types/msg.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | 5 | package mesg.runner.types; 6 | option go_package = "github.com/mesg-foundation/engine/x/runner/internal/types"; 7 | 8 | // The message to create a Runner. 9 | message MsgCreate { 10 | // The Runner's owner. 11 | bytes owner = 1 [ 12 | (gogoproto.moretags) = 'validate:"required,accaddress"', 13 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 14 | ]; 15 | 16 | // Service's hash to start the runner with. 17 | bytes serviceHash = 2 [ 18 | (gogoproto.moretags) = 'validate:"required,hash"', 19 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 20 | ]; 21 | 22 | // Hash of the customized environmental variables (not the ones in the service configuration). 23 | bytes envHash = 3 [ 24 | (gogoproto.moretags) = 'validate:"omitempty,hash"', 25 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 26 | ]; 27 | 28 | } 29 | 30 | // The message to delete a Runner. 31 | message MsgDelete { 32 | // The Runner's owner. 33 | bytes owner = 1 [ 34 | (gogoproto.moretags) = 'validate:"required,accaddress"', 35 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 36 | ]; 37 | 38 | // Runner's hash 39 | bytes hash = 2 [ 40 | (gogoproto.moretags) = 'validate:"required,hash"', 41 | (gogoproto.casttype) = "github.com/mesg-foundation/engine/hash.Hash" 42 | ]; 43 | } 44 | -------------------------------------------------------------------------------- /x/runner/internal/types/querier.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Query endpoints supported by the runner querier 4 | const ( 5 | QueryGet = "get" 6 | QueryList = "list" 7 | QueryExist = "exist" 8 | ) 9 | -------------------------------------------------------------------------------- /x/service/abci.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // BeginBlocker check for infraction evidence or downtime of validators 9 | // on every begin block 10 | func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {} 11 | 12 | // EndBlocker called every block, process inflation, update validator set. 13 | func EndBlocker(ctx sdk.Context, k Keeper) {} 14 | -------------------------------------------------------------------------------- /x/service/alias.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/mesg-foundation/engine/x/service/internal/keeper" 5 | "github.com/mesg-foundation/engine/x/service/internal/types" 6 | ) 7 | 8 | // const aliases 9 | const ( 10 | ModuleName = types.ModuleName 11 | RouterKey = types.RouterKey 12 | StoreKey = types.StoreKey 13 | QuerierRoute = types.QuerierRoute 14 | ) 15 | 16 | // functions and variable aliases 17 | var ( 18 | NewKeeper = keeper.NewKeeper 19 | NewQuerier = keeper.NewQuerier 20 | RegisterCodec = types.RegisterCodec 21 | NewGenesisState = types.NewGenesisState 22 | DefaultGenesisState = types.DefaultGenesisState 23 | ValidateGenesis = types.ValidateGenesis 24 | 25 | ModuleCdc = types.ModuleCdc 26 | 27 | QueryGet = types.QueryGet 28 | QueryList = types.QueryList 29 | QueryExist = types.QueryExist 30 | 31 | EventType = types.EventType 32 | AttributeKeyHash = types.AttributeKeyHash 33 | AttributeKeyAddress = types.AttributeKeyAddress 34 | AttributeActionCreated = types.AttributeActionCreated 35 | ) 36 | 37 | // module types 38 | type ( 39 | Keeper = keeper.Keeper 40 | GenesisState = types.GenesisState 41 | 42 | MsgCreate = types.MsgCreate 43 | ) 44 | -------------------------------------------------------------------------------- /x/service/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | "github.com/cosmos/cosmos-sdk/client/context" 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | "github.com/cosmos/cosmos-sdk/codec" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | "github.com/cosmos/cosmos-sdk/x/auth" 14 | "github.com/cosmos/cosmos-sdk/x/auth/client/utils" 15 | "github.com/mesg-foundation/engine/x/service/internal/types" 16 | "github.com/spf13/cobra" 17 | ) 18 | 19 | // GetTxCmd returns the transaction commands for this module 20 | func GetTxCmd(cdc *codec.Codec) *cobra.Command { 21 | serviceTxCmd := &cobra.Command{ 22 | Use: types.ModuleName, 23 | Short: fmt.Sprintf("%s transactions subcommands", strings.Title(types.ModuleName)), 24 | DisableFlagParsing: true, 25 | SuggestionsMinimumDistance: 2, 26 | RunE: client.ValidateCmd, 27 | } 28 | 29 | serviceTxCmd.AddCommand(flags.PostCommands( 30 | GetCmdCreate(cdc), 31 | )...) 32 | 33 | return serviceTxCmd 34 | } 35 | 36 | // GetCmdCreate is the CLI command for creating a service. 37 | func GetCmdCreate(cdc *codec.Codec) *cobra.Command { 38 | return &cobra.Command{ 39 | Use: "create [definition]", 40 | Short: "Create a service from its definition", 41 | Args: cobra.ExactArgs(1), 42 | RunE: func(cmd *cobra.Command, args []string) error { 43 | inBuf := bufio.NewReader(cmd.InOrStdin()) 44 | cliCtx := context.NewCLIContext().WithCodec(cdc) 45 | 46 | txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 47 | 48 | if cliCtx.FromAddress.Empty() { 49 | return fmt.Errorf("flag --from is required") 50 | } 51 | 52 | rawMsg := fmt.Sprintf(`{"type":"service/create","value":%s}`, args[0]) 53 | var msg types.MsgCreate 54 | if err := cdc.UnmarshalJSON([]byte(rawMsg), &msg); err != nil { 55 | return err 56 | } 57 | if !msg.Owner.Empty() && !msg.Owner.Equals(cliCtx.FromAddress) { 58 | return fmt.Errorf("the owner set in the definition is not the same as the from flag") 59 | } 60 | msg.Owner = cliCtx.FromAddress 61 | if err := msg.ValidateBasic(); err != nil { 62 | return err 63 | } 64 | 65 | return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) 66 | }, 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /x/service/client/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | // RegisterRoutes registers service-related REST handlers to a router 9 | func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { 10 | registerQueryRoutes(cliCtx, r) 11 | registerTxRoutes(cliCtx, r) 12 | } 13 | -------------------------------------------------------------------------------- /x/service/client/rest/tx.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client/context" 5 | "github.com/gorilla/mux" 6 | ) 7 | 8 | func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { 9 | // TODO: 10 | } 11 | -------------------------------------------------------------------------------- /x/service/genesis.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/x/service/internal/types" 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | ) 8 | 9 | // InitGenesis initialize default parameters and the keeper's address to pubkey map. 10 | func InitGenesis(ctx sdk.Context, k Keeper, data types.GenesisState) []abci.ValidatorUpdate { 11 | if err := k.Import(ctx, data.Services); err != nil { 12 | panic(err) 13 | } 14 | return []abci.ValidatorUpdate{} 15 | } 16 | 17 | // ExportGenesis writes the current store values // to a genesis file, 18 | // which can be imported again with InitGenesis. 19 | func ExportGenesis(ctx sdk.Context, k Keeper) types.GenesisState { 20 | services, err := k.List(ctx) 21 | if err != nil { 22 | panic(err) 23 | } 24 | return types.NewGenesisState(services) 25 | } 26 | -------------------------------------------------------------------------------- /x/service/handler.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/x/service/internal/types" 7 | ) 8 | 9 | // NewHandler creates an sdk.Handler for all the service type messages 10 | func NewHandler(k Keeper) sdk.Handler { 11 | return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 12 | ctx = ctx.WithEventManager(sdk.NewEventManager()) 13 | switch msg := msg.(type) { 14 | case MsgCreate: 15 | return handleMsgCreate(ctx, k, &msg) 16 | default: 17 | return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg) 18 | } 19 | } 20 | } 21 | 22 | // handleMsgCreate creates a new process. 23 | func handleMsgCreate(ctx sdk.Context, k Keeper, msg *MsgCreate) (*sdk.Result, error) { 24 | s, err := k.Create(ctx, msg) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | ctx.EventManager().EmitEvent( 30 | sdk.NewEvent( 31 | sdk.EventTypeMessage, 32 | sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), 33 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Owner.String()), 34 | ), 35 | ) 36 | 37 | return &sdk.Result{ 38 | Data: s.Hash, 39 | Events: ctx.EventManager().Events(), 40 | }, nil 41 | } 42 | -------------------------------------------------------------------------------- /x/service/internal/keeper/querier.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/hash" 7 | "github.com/mesg-foundation/engine/x/service/internal/types" 8 | abci "github.com/tendermint/tendermint/abci/types" 9 | ) 10 | 11 | // NewQuerier creates a new querier for service clients. 12 | func NewQuerier(k Keeper) sdk.Querier { 13 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { 14 | switch path[0] { 15 | case types.QueryGet: 16 | return get(ctx, k, path[1:]) 17 | case types.QueryList: 18 | return list(ctx, k) 19 | case types.QueryExist: 20 | return exist(ctx, k, path[1:]) 21 | default: 22 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown service query endpoint") 23 | } 24 | } 25 | } 26 | 27 | func get(ctx sdk.Context, k Keeper, path []string) ([]byte, error) { 28 | if len(path) == 0 { 29 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing hash") 30 | } 31 | hash, err := hash.Decode(path[0]) 32 | if err != nil { 33 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 34 | } 35 | 36 | srv, err := k.Get(ctx, hash) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | res, err := types.ModuleCdc.MarshalJSON(srv) 42 | if err != nil { 43 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 44 | } 45 | return res, nil 46 | } 47 | 48 | func list(ctx sdk.Context, k Keeper) ([]byte, error) { 49 | srvs, err := k.List(ctx) 50 | if err != nil { 51 | return nil, err 52 | } 53 | 54 | res, err := types.ModuleCdc.MarshalJSON(srvs) 55 | if err != nil { 56 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 57 | } 58 | return res, nil 59 | } 60 | 61 | func exist(ctx sdk.Context, k Keeper, path []string) ([]byte, error) { 62 | if len(path) == 0 { 63 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing hash") 64 | } 65 | hash, err := hash.Decode(path[0]) 66 | if err != nil { 67 | return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 68 | } 69 | 70 | exists, err := k.Exists(ctx, hash) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | res, err := types.ModuleCdc.MarshalJSON(exists) 76 | if err != nil { 77 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 78 | } 79 | return res, nil 80 | } 81 | -------------------------------------------------------------------------------- /x/service/internal/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // RegisterCodec registers concrete types on codec 8 | func RegisterCodec(cdc *codec.Codec) { 9 | cdc.RegisterConcrete(MsgCreate{}, "service/create", nil) 10 | } 11 | 12 | // ModuleCdc defines the module codec 13 | var ModuleCdc *codec.Codec 14 | 15 | func init() { 16 | ModuleCdc = codec.New() 17 | RegisterCodec(ModuleCdc) 18 | codec.RegisterCrypto(ModuleCdc) 19 | ModuleCdc.Seal() 20 | } 21 | -------------------------------------------------------------------------------- /x/service/internal/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // module event types and attributes 4 | const ( 5 | EventType = "service" 6 | 7 | AttributeKeyHash = "hash" 8 | AttributeKeyAddress = "address" 9 | 10 | AttributeActionCreated = "created" 11 | ) 12 | -------------------------------------------------------------------------------- /x/service/internal/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/mesg-foundation/engine/hash" 6 | ownershippb "github.com/mesg-foundation/engine/ownership" 7 | ) 8 | 9 | // OwnershipKeeper module interface. 10 | type OwnershipKeeper interface { 11 | Set(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash.Hash, resource ownershippb.Ownership_Resource, resourceAddress sdk.AccAddress) (*ownershippb.Ownership, error) 12 | } 13 | -------------------------------------------------------------------------------- /x/service/internal/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | fmt "fmt" 5 | 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | "github.com/mesg-foundation/engine/service" 8 | ) 9 | 10 | // GenesisState - all instance state that must be provided at genesis 11 | type GenesisState struct { 12 | Services []*service.Service `json:"services" yaml:"services" validate:"dive"` 13 | } 14 | 15 | // NewGenesisState creates a new GenesisState object 16 | func NewGenesisState(services []*service.Service) GenesisState { 17 | return GenesisState{ 18 | Services: services, 19 | } 20 | } 21 | 22 | // DefaultGenesisState is the default GenesisState 23 | func DefaultGenesisState() GenesisState { 24 | return GenesisState{ 25 | Services: []*service.Service{}, 26 | } 27 | } 28 | 29 | // ValidateGenesis validates the instance genesis parameters 30 | func ValidateGenesis(data GenesisState) error { 31 | if err := xvalidator.Struct(data); err != nil { 32 | return fmt.Errorf("failed to validate %s genesis state: %w", ModuleName, err) 33 | } 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /x/service/internal/types/key.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the module 5 | ModuleName = "service" 6 | 7 | // StoreKey to be used when creating the KVStore 8 | StoreKey = ModuleName 9 | 10 | // RouterKey to be used for routing msgs 11 | RouterKey = ModuleName 12 | 13 | // QuerierRoute to be used for routing 14 | QuerierRoute = ModuleName 15 | ) 16 | -------------------------------------------------------------------------------- /x/service/internal/types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/mesg-foundation/engine/ext/xvalidator" 7 | ) 8 | 9 | // Route should return the name of the module route. 10 | func (msg MsgCreate) Route() string { 11 | return RouterKey 12 | } 13 | 14 | // Type returns the action. 15 | func (msg MsgCreate) Type() string { 16 | return "create" 17 | } 18 | 19 | // ValidateBasic runs stateless checks on the message. 20 | func (msg MsgCreate) ValidateBasic() error { 21 | if err := xvalidator.Struct(msg); err != nil { 22 | return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) 23 | } 24 | return nil 25 | } 26 | 27 | // GetSignBytes encodes the message for signing. 28 | func (msg MsgCreate) GetSignBytes() []byte { 29 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 30 | } 31 | 32 | // GetSigners defines whose signature is required. 33 | func (msg MsgCreate) GetSigners() []sdk.AccAddress { 34 | return []sdk.AccAddress{msg.Owner} 35 | } 36 | -------------------------------------------------------------------------------- /x/service/internal/types/msg.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "gogo/protobuf/gogoproto/gogo.proto"; 4 | import "protobuf/types/service.proto"; 5 | 6 | package mesg.service.types; 7 | option go_package = "github.com/mesg-foundation/engine/x/service/internal/types"; 8 | 9 | // The message to create a Service. 10 | message MsgCreate { 11 | // Service's sid. 12 | string sid = 1 [ 13 | (gogoproto.moretags) = 'validate:"omitempty,printascii,max=63,domain"' 14 | ]; 15 | 16 | // Service's name. 17 | string name = 2 [ 18 | (gogoproto.moretags) = 'validate:"required,printascii"' 19 | ]; 20 | 21 | // Service's description. 22 | string description = 3 [ 23 | (gogoproto.moretags) = 'validate:"printascii"' 24 | ]; 25 | 26 | // Configurations related to the service 27 | mesg.types.Service.Configuration configuration = 4 [ 28 | (gogoproto.moretags) = 'validate:"required"', 29 | (gogoproto.nullable) = false 30 | ]; 31 | 32 | // The list of tasks this service can execute. 33 | repeated mesg.types.Service.Task tasks = 5 [ 34 | (gogoproto.moretags) = 'validate:"dive,required"' 35 | ]; 36 | 37 | // The list of events this service can emit. 38 | repeated mesg.types.Service.Event events = 6 [ 39 | (gogoproto.moretags) = 'validate:"dive,required"' 40 | ]; 41 | 42 | // The container dependencies this service requires. 43 | repeated mesg.types.Service.Dependency dependencies = 7 [ 44 | (gogoproto.moretags) = 'validate:"dive,required"' 45 | ]; 46 | 47 | // Service's repository url. 48 | string repository = 8 [ 49 | (gogoproto.moretags) = 'validate:"omitempty,uri"' 50 | ]; 51 | 52 | // The hash id of service's source code on IPFS. 53 | string source = 9 [ 54 | (gogoproto.moretags) = 'validate:"required,printascii"' 55 | ]; 56 | 57 | // The service's owner. 58 | bytes owner = 10 [ 59 | (gogoproto.moretags) = 'validate:"required,accaddress"', 60 | (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" 61 | ]; 62 | } 63 | -------------------------------------------------------------------------------- /x/service/internal/types/querier.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Query endpoints supported by the service querier 4 | const ( 5 | QueryGet = "get" 6 | QueryList = "list" 7 | QueryExist = "exist" 8 | ) 9 | --------------------------------------------------------------------------------