diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..f60c0d39e1c45ed155bedbe44311ee199d7ae4cf --- /dev/null +++ b/.editorconfig @@ -0,0 +1,2 @@ +[Makefile] +indent_style = tab \ No newline at end of file diff --git a/.gitignore b/.gitignore index 90c326000158c0e9a73ee45ee5045085d967d9ca..b037af5cb474f2eb9b52642ac343643eb594c1cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +test_output.xml # Created by https://www.gitignore.io/api/go,vim,emacs,intellij # Edit at https://www.gitignore.io/?templates=go,vim,emacs,intellij diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dd1052e33f7168a169103f9e5f3662fc953a4aa6..8113b3b31db16ddc19ea9400539491c8b2dc51cf 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,24 @@ +variables: + GOPATH: "$CI_PROJECT_DIR/.go" + +cache: + paths: + - .go/pkg/mod + build: image: golang:1.11.5 script: - make install + +test: + image: golang:1.11.5 + script: + - make test + artifacts: + reports: + junit: "TEST_*.xml" + +lint: + image: golang:1.11.5 + script: + - make lint diff --git a/Makefile b/Makefile index c44118ff362e94c0d9ad27f5b132a34463e32df6..8ba80d8076d8de4b85cb01fe97643d6be050b3fb 100644 --- a/Makefile +++ b/Makefile @@ -2,4 +2,11 @@ export GO111MODULE=on install: go install ./cmd/xrnd - go install ./cmd/xrncli \ No newline at end of file + go install ./cmd/xrncli + +test: + go test ./... -godog.strict + +lint: + go get -u golang.org/x/lint/golint + ${GOPATH}/bin/golint -set_exit_status ./... diff --git a/docs/ucr.org b/docs/ucr.org new file mode 100644 index 0000000000000000000000000000000000000000..c814cbb9424dd051b2b84d886aad504a45d266f5 --- /dev/null +++ b/docs/ucr.org @@ -0,0 +1,19 @@ +#+TITLE: Use Cases and Requirements +* Use Cases +* Requirements +** It should be possible to store arbitrary data on the blockchain for a fee + :PROPERTIES: + :CUSTOM_ID: R-StoreData + :END: +** It should be possible to track arbitrary off-chain data by hash on the blockchain, thus generating a proof of timestamp + :PROPERTIES: + :CUSTOM_ID: R-TrackData + :END: +** On-chain and off-chain data should be available in the index available to oracles + :PROPERTIES: + :CUSTOM_ID: R-IndexData + :END: +** There must be a robust way for dealing with hash collisions, especially with respect to off-chain data whose content is opaque + :PROPERTIES: + :CUSTOM_ID: R-HandleHashCollisions + :END: diff --git a/docs/writing_specs.org b/docs/writing_specs.org new file mode 100644 index 0000000000000000000000000000000000000000..688a69552925fa33eb78d19adc89c81854e77640 --- /dev/null +++ b/docs/writing_specs.org @@ -0,0 +1,83 @@ +#+TITLE: Writing Specification Documents + +* Overview and Goals + + This document describes guidelines for writing specification documents. These documents are intended to serve the following purposes: + +- provide the necessary structure to discuss designs while they are in progress before they are built +- provide the blueprints for developers to implement the specified functionality +- serve as documentation once functionality has been implemented + +With these three purposes in mind, specification documents are designed to be useful before, during, and after development. They are intended to be living documents that are upgraded as new use cases are discovered and as the actual implementation changes. + +* General + +** Specifications are written in [[https://orgmode.org][Org Mode]] format + *Rationale:* While org mode is less ubiquitous than Markdown and most well supported in Emacs (though not exclusively), it has some advantages. In particular, we want to leverage Org Babel tangling to keep interface level code in the specification document itself and then have it generated into code. In addition, org mode provides a number of other potentially useful features such as integrated Latex and bibliography support and is in general well supported by Github and Gitlab. Overall it is believed that the benefits, in particular Org Babel, outweigh the learning curve compared to Markdown. + +** Specifications should indicate the implementation status of the specified functionality + As specifications are intended to be living documents that are useful both before and after functionality has been implemented, and as they are intended to be upgraded as new functionality is planned and added, they should indicate the actual implementation status. Status should be indicated under the title using *STATUS:* with one of the following three states: + + - *In Process* to indicate that a specification is being worked on + - *Approved* indicating that a specification has discussed and consensus has been achieved amongst the team + - *Implemented* indicating that the specification reflects the state of the actual code and can thus be used as documentation + + Whenever a specification is out-of-sync with the actual code, a message indicating this can be included next to the status such as "(out of sync with implementation)" to indicate that there is some implementation that differs from this spec. Maintainers should aim not to tag any commit as a release that is out of sync with the implementation because then the documentation is messed up. + +* Organization + Specification documents are to be written for both components and modules. In this context components are defined as individual software artifacts in the build process whereas modules are specific modules specified in Regen Ledger. + +** TODO there should be a root spec file or "table of contents" in the `docs/` folder + +* Component Specifications + Each component (defined as an independent build artifact or separate running process) should have its own ~README.org~ file. We expect have the following components so far: + * Server + * ~xrnd~ blockchain node + * Postgis index of blockchain data + * Jena index of blockchain data + * Client + * ~xrncli~ blockchain client. (Documentation shouldn't duplicate what is available in CLI help) + * Mobile client SDK's - javascript, android, iOS + +* Regen Ledger Module Specifications + Each module in Regen Ledger should have a ~README.org~ document at the root of its folder. This file should contain at a minimum the following sections: + +** Overview + This section describes what the module does at a high-level and includes the definition of any pertinent terms as a source of truth for clarity across the team. + +** Motivation + The motivation section should document why this module ever came into being. What use cases where considered that led to this module being created. Where possible this section should link to other use case and requirements documentation. + +** Transaction Messages and Types + This section defines the public-facing interface for making blockchain transactions. These are the Cosmos SDK messages and other related types that an SDK consumer will use to interact with the module transactionally. Each transaction message as well as important shared types should be documented in a separate section which describes: + - what this message/type does + - any important behavioral notes for both implementers and users + - transaction fees and their rationale + - what ~Tags~ and/or ~Data~ to expect in the transaction response + +*** Org Babel source code + The code for each message/type should be specified in an [[https://orgmode.org/worg/org-contrib/babel/][Org Babel]] code block that gets tangled into ~types.go~. In the preamble to the ~README.org~ file code block (usually with ~:exports none~) should specify a preamble to ~types.go~ that looks something like this (this code block can and should be used as a snippet to start from): + +#+BEGIN_SRC go :tangle types.go :exports none + // GENERATED FROM README.org + // DO NOT EDIT THIS FILE DIRECTLY!!!!! + package data + + import ( + sdk "github.com/cosmos/cosmos-sdk/types" + ) +#+END_SRC + +** Identifiers + + Any identifiers such as blockchain addresses and URL's related to this module should be specified in this section. + +** Indexing and Queries + The projection of module data module to indexes (like Postgresql) as well as queries that should be supported directly against the blockchain should be specified here at a level of rigor comparable to the *Transaction Messages and Types* specifications, including Org Babel code blocks to be tangled into ~types.go~ or other relevant source code files (like SQL schema definitions). + +** Rationale + The rationale for why the implementation described above was chosen should be documented in this section. Where necessary a *Rationale:* paragraph should be included inline in other sections to provide clarity on more specific behavioral choices. + +** CLI Tutorial (optional) + A tutorial walk-through of using the module using the ~xrncli~ command line tool. + diff --git a/go.mod b/go.mod index 58633c6e7683bae2ebbcde534c02d2310741bea4..c4d62817889c00a0406b33b6b5d3e800a0560b96 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,7 @@ module gitlab.com/regen-network/regen-ledger require ( + github.com/DATA-DOG/godog v0.7.10 github.com/ZondaX/hid-go v0.4.0 github.com/ZondaX/ledger-go v0.4.0 github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d @@ -53,15 +54,17 @@ require ( github.com/tendermint/tendermint v0.29.1 github.com/twpayne/go-geom v1.0.4 github.com/zondax/ledger-cosmos-go v0.9.2 - golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 - golang.org/x/net v0.0.0-20181106065722-10aee1819953 + golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 + golang.org/x/net v0.0.0-20190213061140-3a22650c66bd golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 - golang.org/x/text v0.3.0 - google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898 - google.golang.org/grpc v1.16.0 + golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 + google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922 + google.golang.org/grpc v1.17.0 gopkg.in/yaml.v2 v2.2.2 ) replace golang.org/x/crypto => github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5 replace github.com/cosmos/cosmos-sdk => github.com/regen-network/cosmos-sdk v0.19.1-0.20190129211355-6e1f27eea179 // indirect + +// replace github.com/DATA-DOG/godog => github.com/regen-network/godog v0.0.0-0.20190215155814-31cb7bc0e9a6bdc4c3116e54eecbc6ce453d9a2b diff --git a/go.sum b/go.sum index 585246aced8cfcc63d1a2c4a0dc723d3a38d9225..899d671a5c47edaf8ce4139279a63b626e42c135 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,26 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40= +dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DATA-DOG/go-txdb v0.1.2/go.mod h1:aDC9AAfOY+kLbhVTKKXOwkqr2844my+djxj+Ou4wNb4= +github.com/DATA-DOG/godog v0.7.10 h1:BRaQdCOsFth//Ep/J6gtb3xOeDh+sAVjL44ZdK1E9aI= +github.com/DATA-DOG/godog v0.7.10/go.mod h1:z2OZ6a3X0/YAKVqLfVzYBwFt3j6uSt3Xrqa7XTtcQE0= github.com/ZondaX/hid-go v0.4.0/go.mod h1:eaChKpVjUVdM78f1sM/TSFedameXSbNXGiLNvl6sKsA= github.com/ZondaX/ledger-go v0.4.0/go.mod h1:9Q7YMPYFR7tKocUfb8layi5V2tLqZbMs3q0ArLGDFWw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d h1:1aAija9gr0Hyv4KfQcRcwlmFIrhkDmIj2dz5bkg/s/8= github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d/go.mod h1:icNx/6QdFblhsEjZehARqbNumymUT/ydwlLojFdv7Sk= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/btcsuite/btcd v0.0.0-20181130015935-7d2daa5bfef2 h1:LPHpTTuR7vj3kD7YDRZnrDnFAoj1Ov4cpiO3jN8RnW4= github.com/btcsuite/btcd v0.0.0-20181130015935-7d2daa5bfef2/go.mod h1:Jr9bmNVGZ7TH2Ux1QuP0ec+yGgh0gE9FIlkzQiI5bR0= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= @@ -20,6 +33,7 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/cosmos/cosmos-sdk v0.0.0-20190110184329-915ef12facc9/go.mod h1:JrX/JpJunJQXBI5PEX2zELHMFzQr/159jDjIhesOh2c= github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8 h1:Iwin12wRQtyZhH6FV3ykFcdGNlYEzoeR0jN8Vn+JWsI= github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= @@ -27,12 +41,17 @@ github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkE github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-kit/kit v0.6.0 h1:wTifptAGIyIuir4bRyN4h7+kAa2a4eepLYVmRe5qqQ8= github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= @@ -40,25 +59,43 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmhodges/levigo v0.0.0-20161115193449-c42d9e0ca023/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -66,20 +103,27 @@ github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1 h1:K47Rk0v/fkEfwfQet2KWhscE0cJzjgCCDBG2KHZoVno= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181129180645-aa55a523dc0a h1:Z2GBQ7wAiTCixJhSGK4sMO/FHYlvFvUBBK0M0FSsxeU= github.com/prometheus/procfs v0.0.0-20181129180645-aa55a523dc0a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/rakyll/statik v0.1.4 h1:zCS/YQCxfo/fQjCtGVGIyWGFnRbQ18Y55mhS3XPE+Oo= @@ -93,8 +137,38 @@ github.com/regen-network/cosmos-sdk v0.19.1-0.20190129210756-64554b6839f2/go.mod github.com/regen-network/cosmos-sdk v0.19.1-0.20190129211355-6e1f27eea179 h1:YQCak8qFbbv+qgAe4nfJpzevQBwC4hRU/gmMDC5D1c0= github.com/regen-network/cosmos-sdk v0.19.1-0.20190129211355-6e1f27eea179/go.mod h1:NlvB7hxh2AcqplzmTCqBuuRDIb0qYqRo/e/f+0e7BhE= github.com/regen-network/cosmos-sdk v0.25.0 h1:kN3AldBj2T7iFAbuVAWp0gUoT+LkSoWoPNFec3EWXxo= +github.com/regen-network/godog v0.0.0-0.20190129211355-31cb7bc0e9a6bdc4c3116e54eecbc6ce453d9a2b h1:ooHtFX8t08wbC3MoR6wWNC+uwJ9lv1ExrIvcNPtxKvs= +github.com/regen-network/godog v0.0.0-0.20190129211355-31cb7bc0e9a6bdc4c3116e54eecbc6ce453d9a2b/go.mod h1:tZx0qfvDOzsmFkvWYZI/JNPPqQb77S76qZKwH31KQl0= +github.com/regen-network/godog v0.0.0-0.20190215155814-31cb7bc0e9a6bdc4c3116e54eecbc6ce453d9a2b h1:6/0kKxUPEwmwC6nPN8oq+9idO3ll5kzhqoqukdvAGTs= +github.com/regen-network/godog v0.0.0-0.20190215155814-31cb7bc0e9a6bdc4c3116e54eecbc6ce453d9a2b/go.mod h1:tZx0qfvDOzsmFkvWYZI/JNPPqQb77S76qZKwH31KQl0= github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= @@ -112,6 +186,7 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2 h1:GnOzE5fEFN3b2zDhJJABEofdb51uMRNb8eqIVtdducs= github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tendermint/btcd v0.0.0-20180816174608-e5840949ff4f h1:R0wLxgASGMoRQTF/dCSk4N+M3j9DLyPDzDff2WtCg/I= github.com/tendermint/btcd v0.0.0-20180816174608-e5840949ff4f/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5 h1:u8i49c+BxloX3XQ55cvzFNXplizZP/q00i+IlttUjAU= @@ -131,28 +206,73 @@ github.com/twpayne/go-geom v1.0.4/go.mod h1:Xt2LAX0JiP94UWCnKKpDtx/d5g94AQNOCbms github.com/twpayne/go-kml v1.0.0/go.mod h1:LlvLIQSfMqYk2O7Nx8vYAbSLv4K9rjMvLlEdUKWdjq0= github.com/twpayne/go-polyline v1.0.0/go.mod h1:ICh24bcLYBX8CknfvNPKqoTbe+eg+MX1NPyJmSBo7pU= github.com/zondax/ledger-cosmos-go v0.9.2/go.mod h1:uhu/ldrtzhUH7RoWoTKK4MxBi/CXfyViVA0OCYTiHdM= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1 h1:rJm0LuqUjoDhSk2zO9ISMSToQxGz7Os2jRiOL8AWu4c= +golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/net v0.0.0-20180710023853-292b43bbf7cb/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953 h1:LuZIitY8waaxUfNIdtajyE/YzA/zyf0YxXG27VpLrkg= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU= golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52 h1:JG/0uqcGdTNgq7FdU+61l5Pdmb8putNZlXb65bJBROs= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190214204934-8dcb7bc8c7fe h1:oou9Na+8DBZO/hrVPAjBTaHXmuDq0284mwGwfmQ4ids= +golang.org/x/tools v0.0.0-20190214204934-8dcb7bc8c7fe/go.mod h1:E6PF97AdD6v0s+fPshSmumCW1S1Ne85RbPQxELkKa44= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898 h1:yvw+zsSmSM02Z5H3ZdEV7B7Ql7eFrjQTnmByJvK+3J8= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922 h1:mBVYJnbrXLA/ZCBTCe7PtEgAUP+1bg92qTaFoPHdz+8= +google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0 h1:dz5IJGuC2BB7qXR5AyHNwAUBhZscK2xVez7mznh72sY= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/x/.gitignore b/x/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..0b84df0f0253112e776e30cc1b7f1b7b9182e8b6 --- /dev/null +++ b/x/.gitignore @@ -0,0 +1 @@ +*.html \ No newline at end of file diff --git a/x/action/README.org b/x/action/README.org new file mode 100644 index 0000000000000000000000000000000000000000..bcc69e3057280a52acf13eeae9cb1db7fb6db33e --- /dev/null +++ b/x/action/README.org @@ -0,0 +1,111 @@ +#+BEGIN_SRC go + type ActionDispatcher interface { + DispatchAction(ctx sdk.Context, actor Actor, action Action) ActionResult + } + + type CapabilityKeeper interface { + // Store capabilities under the key actor-id/capability-id + // Grant stores a root flag, and delegate + GrantRootCapability(ctx sdk.Context, actor sdk.AccAddress, capability ActionCapability) + RevokeRootCapability(ctx sdk.Context, actor sdk.AccAddress, capability ActionCapability) + Delegate(ctx sdk.Context, grantor sdk.AccAddress, actor sdk.AccAddress, capability ActionCapability) + Undelegate(ctx sdk.Context, grantor sdk.AccAddress, actor sdk.AccAddress, capability ActionCapability) + HasCapability(ctx sdk.Context, actor sdk.AccAddress, capability ActionCapability) bool + } + + type capabilityGrant { + // set if this is actor should be granted the capability at a "root" level + root bool + // all the actors that delegated this capability to the actor + // the capability should be cleared if root is false and this array is cleared + delegatedBy []sdk.AccAddress + + // whenever this capability is undelegated or revoked, these delegations + // need to be cleared recursively + delegatedTo []sdk.AccAddress + } + + type sdk.AccAddress []byte + + type Actor interface { + sdk.AccAddress() sdk.AccAddress + } + + type Action interface { + RequiredCapabilities() []ActionCapability + // Return the message type. + // Must be alphanumeric or empty. + Route() string + + // Returns a human-readable string for the message, intended for utilization + // within tags + Type() string + + // ValidateBasic does a simple validation check that + // doesn't require access to any other information. + ValidateBasic() sdk.Error + + // Get the canonical byte representation of the Msg. + GetSignBytes() []byte + + //HandleProposal(ctx sdk.Context, votes []sdk.AccAddress) sdk.Result + } + + type ActionResult interface { + } + + type ActionCapability interface { + // Every capability should be have a system wide unique ID that includes + // both the type of capability and any params associated with it + CapabilityID () String + // Whether the specified action is allowed by this capability + Accept(action Action) Bool + //// Whether capability is a sub-capability of this capability + //IsSubCapability(capability ActionCapability) Bool + //// TODO return who delegated the capability so it can be undelegated + //Delegator() interface{} + //// or maybe: + //CanUndelegate (credential interface{}) Bool + } + + type SendAction struct { + } + + type SendActionCapability struct { + Account sdk.AccAddress + } + + type IssueESPResultAction struct { + Geo GeoID + ESP ESP_ID + Claim DataID + } + + type IssueESPResultActionCapability struct { + ESP ESP_ID + } + + // issues a credential to some identity (key or address), probably just sdk.AccAddress + type IssueCredentialAction struct { + Subject sdk.AccAddress + Credential CredentialID + Claim DataID + } + + type MintAction struct { + } + + type CreateContractAction struct { + Code data.DataID + InitialState data.DataID + Capabilities []ActionCapability + // TODO initial coins + } + + type DelegateAction struct { + Capabilities []ActionCapability + } + + type UndelegateAction struct { + } +#+END_SRC go diff --git a/x/agent/README.md b/x/agent/README.md deleted file mode 100644 index b6fe5674fda39467e92bf28ead0fbe626a893373..0000000000000000000000000000000000000000 --- a/x/agent/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Agent Module - -The agent module provides a mechanism that can be used to support basic -multi-party organizations and to allow individuals to facilitate authorization -via multiple keys. In the future, it may be extended to support more sophisticated -multi-party authorization schemes. \ No newline at end of file diff --git a/x/agent/README.org b/x/agent/README.org new file mode 100644 index 0000000000000000000000000000000000000000..e50de976b9c74a8df4d14d7ac2b26ab10b6de3fe --- /dev/null +++ b/x/agent/README.org @@ -0,0 +1,105 @@ +#+TITLE: Group Module +*STATUS: In Process* (out of sync with implementation) + +#+BEGIN_SRC go :tangle types.go :exports none + // GENERATED FROM README.org + // DO NOT EDIT THIS FILE DIRECTLY!!!!! + package group + + import ( + sdk "github.com/cosmos/cosmos-sdk/types" + ) +#+END_SRC + +* Overview + + A ~Group~ is an aggregation of Regen Ledger addresses - which themselves can be individual keys, other groups, or contracts - each with an associated voting ~Weight~ and a ~DecisionThreshold~. This allows for specifying on-chain organizations as well as arbitrary groups of keys that have a governance structure that includes simple majority, super-majority, minority approval, and weighted ownership. In the future, it may be extended to support more sophisticated multi-party authorization schemes. + +* Motivation + There are a number of scenarios where we want to model a group or organization concept on the blockchain. Here are some hypothesized groups that this module should serve: + +** Regen Consortium and its member organizations + The Regen Consortium is intended to be the group of organizations that govern the Regen Ledger blockchain. They get to choose the validator set, decide on major upgrades to the blockchain as well as a number of parameters like transaction fees. Each consortium member itself must be an organization that likely has its own decision making policy. + +** Protocol and Contract Curators + Ecological state protocols (ESPs) and contracts (ECs) have been theorized to specify some organization or group that "curates" them. Curation has a number of different benefits and responsibilities. ESP curators have the responsibility of upgrading the protocols over time and may also receive curator fees when ESPs are run. EC curators may also receive a fee and/or be required to intervene to arbitrate terms of a contract. + +** Verifiers + It is hypothesized that verifiers may likely be multi-party organizations that have their own governance protocol for approving verification claims. + +* Transaction Messages and Types +** Basic Types +#+BEGIN_SRC go :tangle types.go +// A group can be used to abstract over users and groups. +// It could be used to group individuals into a group or several groups/users into a larger group. +// It could be used by a single user to manage multiple devices and setup a multisig policy. +type Group struct { + // The members of the group and their associated weight + Members []Member `json:"addresses,omitempty"` + // Specifies the number of votes that must be accumulated in order for a decision to be made by the group. + // A member gets as many votes as is indicated by their Weight field. + // A big integer is used here to avoid any potential vulnerabilities from overflow errors + // where large weight and threshold values are used. + DecisionThreshold big.Int `json:"decision_threshold"` + // TODO maybe make this something more specific to a domain name or a claim on identity? or Memo leave it generic + Memo string `json:"memo,omitempty"` +} + +// A member specifies a address and a weight for a group member +type Member struct { + // The address of a group member. Can be another group or a contract + Address sdk.AccAddress `json:"address"` + // The integral weight of this member with respect to other members and the decision threshold + Weight big.Int `json:"weight,omitempty"` +} +#+END_SRC go +** ~MsgCreateAgent~ + + /[[./features/create.feature][Test spec]]/ + +#+BEGIN_SRC go :tangle types.go +// Creates a group on the blockchain +// Should return a tag "group.id" with the bech32 address of the group +type MsgCreateGroup struct { + Data Group `json:"data"` + Signer sdk.AccAddress `json:"signer"` +} +#+END_SRC + +#+BEGIN_SRC gherkin :tangle features/create.features +Feature: Create group + Scenario: Create a group from a single key + Given a public key address + When a user creates a group with that address + And a decision threshold of 1 + Then they should get a new group address back +#+END_SRC +*** TODO transaction fee + +* Identifiers + Groups implement the ~Account~ interface and thus have an ~AccAddress~. Internally an group ID is an ~uint64~ which is assigned on an auto-increment basis. The ~AccAddress~ for an group is made by concatenating the prefix ~G~ (as ~[]byte~) and the [[https://golang.org/pkg/encoding/binary/#PutUvarint][varint]] encoding of the ~uint64~ account ID. The textual representation of an group account is obtained by taking the bech32 encoding of this ~AccAddress~ with the prefix ~xrn:~ which also is a valid URI. + +* Indexing and Queries +** ~get~ + + /[[./features/get.feature][Test spec]]/ + + The ~get~ query command should take the group address as a single parameter retrieve the current ~Group~ struct (as JSON) associated with that address +** Postgresql + Groups and their members should be indexed to the tables below which should allow members to look up any groups they are directly or transitively part of: + +#+BEGIN_SRC sql :tangle group.sql + CREATE TABLE group ( + address text NOT NULL PRIMARY KEY, + threshold NUMERIC NOT NULL + ); + + CREATE TABLE group_member ( + group text NOT NULL REFERENCES group, + address text NOT NULL, + weight NUMERIC NOT NULL + ) +#+END_SRC + +* Rationale + Groups are designed with a simple weight/threshold voting mechanism. Other voting mechanisms could be added to the ~Group~ type in the future, but for now this simple mechanism is theorized to be sufficient for most of our immediate use cases. To begin with ~DecisionThreshold~ allows for any sort of majority of super-majority voting system where all members have equal weight. It also allows for minority voting systems where say we are managing our own keys and have several devices but only need say two at a time to approve a transaction. The addition of the ~Weight~ parameter for each member allows for managing voting scenarios where weight is distributed unequally - say in ownership shares of a company. So if persons A, B, and C each had 1000 shares and person D had 2000 shares, we could set their ~Weight~'s to their share count and ~DecisionThreshold~ to 2501 for simply majority approval. Many other governance mechanisms that are more complex could actually be handled by nesting groups with different responsibilities. For instance say we had a reporter/approver approval mechanism for an ESP report. We could have a group of reporters in a group with equal weight and ~DecisionThreshold~ 1, and a similar group for approvers, and then join them into a reporter/approver group where the reporter group and approver group are each members with ~Weight~ 1 and ~DecisionThreshold~ 2. This arrangements specifies that we need one reporter and one approver to sign off on a report. While there are scenarios that definitely can't be handled with this type of governance definition, there are a surprisingly large number that can and so our hypothesis is that this is sufficient to start until more scenarios are encountered. diff --git a/x/agent/features/create.feature b/x/agent/features/create.feature new file mode 100644 index 0000000000000000000000000000000000000000..4748f8d65252da32b6dec817fe031cb8a2dc9d77 --- /dev/null +++ b/x/agent/features/create.feature @@ -0,0 +1,6 @@ +Feature: Create group + Scenario: Create a group from a single key + Given a public key address + When a user creates a group with that address + And a decision threshold of 1 + Then they should get a new group address back \ No newline at end of file diff --git a/x/agent/features/get.feature b/x/agent/features/get.feature new file mode 100644 index 0000000000000000000000000000000000000000..632eb4632a1929164dd8630355d8b98122131198 --- /dev/null +++ b/x/agent/features/get.feature @@ -0,0 +1,5 @@ +Feature: Get group details + Scenario: + Given a group ID + When a user gets the group details on the command line + Then they should get back the group details in JSON format \ No newline at end of file diff --git a/x/agent/group_test.go b/x/agent/group_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4361b20c04e6c49ebd9aa506bfc8ef8ab09e5ea2 --- /dev/null +++ b/x/agent/group_test.go @@ -0,0 +1,83 @@ +package agent + +import ( + "flag" + "github.com/DATA-DOG/godog" + "github.com/DATA-DOG/godog/colors" + "os" + "testing" +) + +var opt = godog.Options{ + Output: colors.Colored(os.Stdout), + Format: "progress", // can define default values +} + +func init() { + godog.BindFlags("godog.", flag.CommandLine, &opt) +} + +func TestMain(m *testing.M) { + /*const suiteName = "group" + ci, found := os.LookupEnv("CI") + if found && len(ci) != 0 { + testfileName := fmt.Sprintf("%s/TEST_%s.xml", os.Getenv("CI_PROJECT_DIR"), suiteName) + f, err := os.Create(testfileName) + if err != nil { + fmt.Printf("Error creating test output file %s: %+v", testfileName, err) + } else { + opt.Output = f + opt.Format = "junit" + } + }*/ + + flag.Parse() + opt.Paths = flag.Args() + + status := godog.RunWithOptions("godogs", func(s *godog.Suite) { + FeatureContext(s) + }, opt) + + if st := m.Run(); st > status { + status = st + } + os.Exit(status) +} + +func aPublicKeyAddress() error { + return godog.ErrPending +} + +func aUserCreatesAGroupWithThatAddress() error { + return godog.ErrPending +} + +func aDecisionThresholdOf(arg1 int) error { + return godog.ErrPending +} + +func theyShouldGetANewGroupAddressBack() error { + return godog.ErrPending +} + +func aGroupID() error { + return godog.ErrPending +} + +func aUserGetsTheGroupDetailsOnTheCommandLine() error { + return godog.ErrPending +} + +func theyShouldGetBackTheGroupDetailsInJSONFormat() error { + return godog.ErrPending +} + +func FeatureContext(s *godog.Suite) { + s.Step(`^a public key address$`, aPublicKeyAddress) + s.Step(`^a user creates a group with that address$`, aUserCreatesAGroupWithThatAddress) + s.Step(`^a decision threshold of (\d+)$`, aDecisionThresholdOf) + s.Step(`^they should get a new group address back$`, theyShouldGetANewGroupAddressBack) + s.Step(`^a group ID$`, aGroupID) + s.Step(`^a user gets the group details on the command line$`, aUserGetsTheGroupDetailsOnTheCommandLine) + s.Step(`^they should get back the group details in JSON format$`, theyShouldGetBackTheGroupDetailsInJSONFormat) +} diff --git a/x/agent/types.go b/x/agent/types.go index b95aa166f212d205ad5143d5060944d30a35a840..58c081e8180b61fd7c32d96533a5ba625b6a51ee 100644 --- a/x/agent/types.go +++ b/x/agent/types.go @@ -24,4 +24,3 @@ type AgentInfo struct { MultisigThreshold int `json:"multisig_threshold"` Memo string `json:"memo,omitempty"` } - diff --git a/x/contracts/README.org b/x/contracts/README.org new file mode 100644 index 0000000000000000000000000000000000000000..4da28a2c5ec27e1b0adec39b8e2c5148afc58c12 --- /dev/null +++ b/x/contracts/README.org @@ -0,0 +1,158 @@ +* FSM approach + +#+BEGIN_SRC go + // A contract template + type Contract struct { + States []State + } + + type State struct { + Name string + // Sparql CONSTRUCT's that should be executed + // when entering this state + OnEnter []string + // Sparql CONSTRUCT's that should be executed + // when re-entering this state + OnReEnter []string + // Sparql select that should be executed when entering or + // re-entering this state to get the next transition time + // (the time when the transition clauses should be executed + // until one of them succeeds or they all fail and a re-enter + // occurs) + GetTransitionTime string + Transitions []Transition + } + + type Transition struct { + // state this transition would go to + To string + // Sparql ASK query that returns true if the state + // transition should go forward + ShouldTransition string + // Sparql CONSTRUCT's that should be executed + // when exiting this state on this transition branch + OnExit []string + } + + type ContractState struct { + balance sdk.Coins + state string + // The parameters the contract instance was initialized with + parameters string + nextTransitionTime time.Time + } +#+END_SRC go + +#+BEGIN_SRC trig +_:a a xrn:DepositRecepit ; + xrn:to ; + xrn:coins [ + xrn:denom "XRN" . + xrn:amount 1234 . + ]. + +_:b a xrn:EscrowInitializer ; + xrn:contractTemplate ; + xrn:contractParams _:params ; + xrn:coins [ + xrn:denom "XRN" . + xrn:amount 2345 . + ]. + +_:params { + +} +#+END_SRC + +** Sparql ASK and CONSTRUCT + Sparql ASK and CONSTRUCT are basic building blocks of this approach to constructs, with ASK queries being the boolean condition that guards transition between states and CONSTRUCT expressions being used to create events such as payments, minting, contract creation, and claim signing on state transitions. +* Minimum Knowledge State Machine Approach + This approach could work with the above state machine approach but offloads the whole knowledge of code to just some data that gets pointed to and maybe has a schema. There needs to be specification on what valid code formats are for oracle consensus, but the blockchain itself only needs to know pointers to the code and current state and receive the actions that occur on transitions. + +#+BEGIN_SRC go + type ProcessingState int + + const ( + CanAcceptInput ProcessingState = 0 + Transitioning + ChallengeWindow + Finalized + ) + + type ContractState struct { + balance sdk.Coins + code data.DataID + contractState data.DataID + processingState ProcessingState + capabilities []ActionCapability + // TODO transition/challenge time window + // TODO oracle requirements + // TODO arbiter + } +#+END_SRC go + +** Contract Actions + +#+BEGIN_SRC go + type ActorID []byte + + // Wraps both agents and contracts which can have capabilities + type ActorKeeper interface { + func Delegate(actor ActorID, capabilities []ActionCapability) + // TODO Undelegate + } + + type Action interface { + } + + type ActionCapability { + // Whether the specified action is allowed by this capability + func Accept(action Action) Bool + // Whether capability is a sub-capability of this capability + func IsSubCapability(capability ActionCapability) Bool + // TODO return who delegated the capability so it can be undelegated + func Delegator() interface{} + // or maybe: + func CanUndelegate (credential interface{}) Bool + } + + type SendAction struct { + } + + type SendActionCapability struct { + Account sdk.AccAddress + } + + type IssueESPResultAction struct { + Geo GeoID + ESP ESP_ID + Claim DataID + } + + type IssueESPResultActionCapability struct { + } + + // issues a credential to some identity (key or address), probably just sdk.AccAddress + type IssueCredentialAction struct { + Subject sdk.AccAddress + Credential CredentialID + Claim DataID + } + + type MintAction struct { + } + + type CreateContractAction struct { + Code data.DataID + InitialState data.DataID + Capabilities []ActionCapability + // TODO initial coins + } + + type DelegateAction struct { + Capabilities []ActionCapability + } + + type UndelegateAction struct { + } +#+END_SRC go diff --git a/x/data/README.md b/x/data/README.md deleted file mode 100644 index 49a21ac0ef778f951e766af33c26cd319369319b..0000000000000000000000000000000000000000 --- a/x/data/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Data Module - -This module provides very basic support for hashing and time-stamping data onto -the blockchain. It serves the purpose of providing a way that any piece of data -can be tracked onto the blockchain for a fee and known to have existed at or -before some given block-height. It is intended that this module will mostly -be supplanted by other more domain specific functionality and/or -enhanced with robust, opt-in schema-validation support in the future. \ No newline at end of file diff --git a/x/data/README.org b/x/data/README.org new file mode 100644 index 0000000000000000000000000000000000000000..b304bc112f80a175e7e491813ef4d3adce1b531c --- /dev/null +++ b/x/data/README.org @@ -0,0 +1,147 @@ +#+TITLE: Data Module +*STATUS: PARTIAL* +* Overview + :PROPERTIES: + :CUSTOM_ID: overview + :END: + +This module provides very basic support for hashing and time-stamping data onto +the blockchain. It serves the purpose of providing a way that any piece of data +can be tracked onto the blockchain for a fee and known to have existed at or +before some given block-height. It is intended that this module will mostly +be supplanted by other more domain specific functionality and/or +enhanced with robust, opt-in schema-validation support in the future. + +* Motivation and Rationale + + +** Requirements + :PROPERTIES: + :CUSTOM_ID: overview + :END: + +- It should be possible to store arbitrary data on the blockchain for a fee +- It should be possible to track arbitrary off-chain data by hash on the blockchain, thus generating a proof of timestamp +- On-chain and off-chain data should be available in the index available to oracles +- There must be a robust way for dealing with hash collisions, especially with respect to off-chain data whose content is opaque + +* Transaction Messages and Types +#+BEGIN_SRC go :tangle types.go :exports none + // GENERATED FROM README.org + // DO NOT EDIT THIS FILE DIRECTLY!!!!! + package data + + import ( + sdk "github.com/cosmos/cosmos-sdk/types" + ) +#+END_SRC + +** Store RDF graph on-chain + +#+BEGIN_SRC go :tangle types.go + type MsgStoreGraph struct { + // RDF graph data in N-Triples text format with no blank nodes allowed! + NTriples string `json:"ntriples"` + // Expected hash of the graph. The transaction will be rejected if this hash can't be verified. + URDNA2015_BLAKE2B_256_Hash []byte `json:"urdna2015_blake2b_256_hash"` + Signer sdk.AccAddress `json:"signer"` + } +#+END_SRC + +[[https://www.w3.org/TR/n-triples/][N-Triples]] format has been chosen as a starting point because it is easy to parse and self-contained. **Blank nodes are not allowed in on-chain graphs!** This restriction makes it easy to verify that the dataset is canonicalized and that the hash matches, without having to run the full canonicalization algorithm on-chain. The N-Triples data passed in must be in canonicalized form which essentially means that it is sorted because blank nodes are not allowed. + +*** NOTE The reason JSON-LD has not been chosen for on-chain usage is that the way `@context` is designed explicitly requires JSON-LD processors to pull off-chain HTTP data which is indeterministic. + +*** TODO In the future, we would like to support a compact binary format. + +*** TODO should data schema (i.e. SCHACL/SHEX/JSON-SCHEMA) be tracked and/or verified on-chain? + It might be useful to track format on-chain but not verify it. For a given format there could be multiple schemas that it satisfies. My current thoughts are that this is a type of verification/validation that can be done off chain and there can be on-chain attestations about that - ARC. + +** Track off-chain RDF dataset + +#+BEGIN_SRC go :tangle types.go + type MsgTrackDataset struct { + URDNA2015_BLAKE2B_256_Hash []byte `json:"urdna2015_blake2b_256_hash"` + Url string `json:"url,omitempty"` + Signer sdk.AccAddress `json:"signer"` + } +#+END_SRC + +*** TODO should data stores that reference off-chain data have their own on-chain reference and data tracking instead of a URL just reference the service via which it can be retrieved by hash? + i.e. if we know the service ID we can just do an HTTP GET for ~/~. + +** Track arbitrary off-chain data + +#+BEGIN_SRC go :tangle types.go + type HashAlgorithm int + + const ( + BLAKE2B_256 HashAlgorithm = 0 + SHA256 HashAlgorithm = 1 + ) + + type MsgTrackData struct { + Hash []byte `json:"hash"` + Algorithm HashAlgorithm `json:"algorithm"` + Url string `json:"url,omitempty"` + Signer sdk.AccAddress `json:"signer"` + } +#+END_SRC + +** TODO Store arbitrary data on-chain + This is a use case we may want to support but for now are not supporting it because it is questionable whether we should encourage storing data on-chain that can't be interpreted by other on-chain infrastructure. + +** TODO allow for tracking off-chain data which has a salt/nonce introduced + +** TODO allow for multiple URL's to be provided for off-chain data and to allow possible ways to deal with hash collisions + +** TODO possibly make URL's for off-chain data optional + +** TODO support for tracking the merkle roots of off-chain data stores + This should probably be coordinated with the IBC spec + +* Identifiers +** On-chain graphs + On-chain graphs are identified by the URI formed by encoding the URNDNA2015_BLAKE2B_256 hash of the graph with the prefix ~xrn:///g/~. +** Off-chain datasets + Off-chain datasets are identified by the URI formed by encoding the URNDNA2015_BLAKE2B_256 hash of the dataset with the prefix ~xrn:///ds/~. +** Off-chain raw data + Off-chain raw data is identified by the URI formed by encoding the Blake2b 256-bit hash of the data prefixed with ~xrn:///dt/~. +** On-chain raw data?? + On-chain raw data is identified by the URI formed by encoding the Blake2b 256-bit hash of the data prefixed with ~xrn:///da/~. +* Indexing and Queries +** Postgresql +#+BEGIN_SRC sql :tangle data.sql + CREATE TABLE "data" ( + uri text NOT NULL PRIMARY KEY, + tx bytea NOT NULL REFERENCES tx, + graph jsonb + --raw_data bytea + ); + + COMMENT ON COLUMN graph.graph IS 'The JSON-LD expanded form representation of an on-chain graph'; + + COMMENT ON COLUMN graph.raw_data IS 'Raw data bytes for on-chain raw data'; +#+END_SRC +** RDF +*** Schema +#+BEGIN_SRC turtle +PREFIX rdf: +PREFIX rdfs: +PREFIX xsd: +PREFIX xrn: + +xrn:urdna2015Blake2b256Hash a rdf:Property ; + rdfs:range xsd:base64Binary . + +#+END_SRC +*** On-chain graphs + On chain graphs are indexed in the RDF store in the named graph identified with the graph identifier URI. They are annotated in the default graph as follows (where ~xrn://12345/g/1xq52sutm~ is an example graph URI): + +#+BEGIN_SRC turtle +PREFIX xrn: + + + xrn:tx ; + xrn:urdna2015Blake2b256Hash "sdgbhABN38dsfgn23t=" . +#+END_SRC diff --git a/x/data/schema.json b/x/data/schema.json deleted file mode 100644 index e1f0ab43cf7e80612f6ee2d68199ecc5b49fdff9..0000000000000000000000000000000000000000 --- a/x/data/schema.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "definitions":{ - "MsgRegisterSchema":{ - "title":"MsgRegisterSchema", - "type":"Object", - "properties":{ - } - } - } -} diff --git a/x/esp/README.md b/x/esp/README.md deleted file mode 100644 index 36f665c204f97256b87f60bdcd6eda7f745566a6..0000000000000000000000000000000000000000 --- a/x/esp/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# ESP module - -The ESP (ecological state protocol) module provides a global geo-tagged, ledger of ecological health. - -ESP's are managed by curating organizations (managed by the [agent](../agent/README.md) module) and can evolve through -various versions as the curating organization refines its verification methodology. Curators are responsible for -defining approved verifiers and a schema for ESP results. - -All ESP results include a geo-polygon that allows the data stored in the ESP result registry to be projected onto a map - for visualization of global ecological health. \ No newline at end of file diff --git a/x/esp/README.org b/x/esp/README.org new file mode 100644 index 0000000000000000000000000000000000000000..13af8cab6b151ae5102f47d0c25485d6889f8dee --- /dev/null +++ b/x/esp/README.org @@ -0,0 +1,53 @@ +#+TITLE: ESP module + +* Overview + +The ESP (ecological state protocol) module provides a global geo-tagged, ledger of ecological health. + +ESP's are managed by curating organizations (managed by the [[../agent/README.org][agent]] module) and can evolve through +various versions as the curating organization refines its verification methodology. Curators are responsible for +defining approved verifiers and a schema for ESP results. + +All ESP results include a geo-polygon that allows the data stored in the ESP result registry to be projected onto a map +for visualization of global ecological health. + +* Motivation and Rationale + +* Transaction Messages and Types + +#+BEGIN_SRC go +type ESPVersionID []byte + +type ESPVersionSpec { + Curator sdk.AccAddress `json:"curator"` + Name string `json:"name"` + Version string `json:"version"` + Verifiers []sdk.AccAddress `json:"verifiers"` + // TODO ClaimSchema schema.SchemaID?? +} + +type ESPResult struct { + ESP ESPVersionID + Verifier sdk.AccAddress `json:"verifier"` + Geo geo.GeoID + Claim data.DataID +} + +type ActionRegisterESPVersion struct { + Curator sdk.AccAddress `json:"curator"` + Name string `json:"name"` + Version string `json:"version"` + Verifiers []sdk.AccAddress `json:"verifiers"` +} + +type ActionReportESPResult struct { + ESP ESPVersionID + Geo geo.GeoID + Claim data.DataID +} +#+END_SRC go + +* Identifiers + ESP's are identified by the URI formed by taking the agent URI and appending ~/esp//+~. + +* Indexing and Queries diff --git a/x/geo/README.org b/x/geo/README.org new file mode 100644 index 0000000000000000000000000000000000000000..2082d0fa9fae83bd1e63f42306cca19050254236 --- /dev/null +++ b/x/geo/README.org @@ -0,0 +1,78 @@ +#+TITLE: Geo Module +#+BEGIN_SRC go :tangle types.go :exports none + /* GENERATED FROM README.org + DO NOT EDIT THIS FILE DIRECTLY!!!!! */ + + package geo + + import ( + sdk "github.com/cosmos/cosmos-sdk/types" + ) +#+END_SRC +#+BEGIN_SRC sql :tangle geo.sql :exports none + /* GENERATED FROM README.org + DO NOT EDIT THIS FILE DIRECTLY!!!!! */ + +#+END_SRC +* Overview + The ~geo~ module provides an efficient storage space for on-chain geographic features that can be referenced by other modules. +* Motivation and Rationale + While geographic features could be stored as literals everywhere they are needed, precise measurements of real world objects like a polygon that describes an irregularly shaped field can become quite large because of the number of points required to be precise. Having a single storage space for these objects reduces overall storage requirements. Geographic features are also referenced by hash on-chain which provides for content addressability and reduces duplication. +* Transaction Messages and Types +** TODO Store geographic feature on-chain +#+BEGIN_SRC go :tangle types.go + type MsgStoreGeo struct { + Data Geometry `json:"data"` + Signer sdk.AccAddress `json:"signer"` + } + + type FeatureType int + + const ( + Point FeatureType = 0 + LineString + Polygon + MultiPoint + MultiLineString + MultiPolygon + ) + + type Geometry struct { + Type FeatureType `json:"type"` + // EWKB representation of the geo feature. Must be in the WGS84 coordinate + // system and represent a Point, LineString, Polygon, MultiPoint, MultiLineString or MultiPolygon + EWKB []byte `json:"ewkb,omitempty"` + } +#+END_SRC +*** TODO we probably don't need to store points here, no use for anything other than polygons here +*** TODO should this module provide support for off-chain geo-features for protecting privacy?? + Should this support include some sort of nonce support like in data? + +** Identifiers +*** TODO ~Geometry~ URI's + Stored ~Geometry~'s are referenced by the URI created by the bech32 encoding of the Blake2b 256-bit hash of the EWKB representation of the geographic feature prefixed with ~xrn:///geo/~. +** Indexing and Queries + Geographic features are indexed by both the Postgis and RDF indexers. +*** TODO Postgis + ~Geometry~'s will be indexed in the table ~geo~ defined as: +#+BEGIN_SRC sql :tangle geo.sql + CREATE TABLE geo ( + uri text NOT NULL PRIMARY KEY, + tx bytea NOT NULL REFERENCES tx, + -- Both the Postgis geography and geometry representations are stored + geog geography NOT NULL, + geom geometry NOT NULL + ); + + CREATE INDEX geo_geom_gist ON geo USING GIST ( geom ); +#+END_SRC +*** TODO RDF + ~Geometry~'s will be indexed in the RDF store as below and available in both the default graph and the named graph identified by the ~Geometry~ URI. +#+BEGIN_SRC turtle +PREFIX geo: +PREFIX sf: + + + a sf:Point ; + geo:asWKT "Point(-83.38 33.95)"^^ . +#+END_SRC diff --git a/x/geo/geo.sql b/x/geo/geo.sql new file mode 100644 index 0000000000000000000000000000000000000000..be0ff087ebd2bebc6de550141d58179456204a2f --- /dev/null +++ b/x/geo/geo.sql @@ -0,0 +1,12 @@ +/* GENERATED FROM README.org + DO NOT EDIT THIS FILE DIRECTLY!!!!! */ + +CREATE TABLE geo ( + hash bytea NOT NULL PRIMARY KEY, + tx bytea NOT NULL REFERENCES tx, + -- Both the Postgis geography and geometry representations are stored + geog geography NOT NULL, + geom geometry NOT NULL +); + +CREATE INDEX geo_geom_gist ON geo USING GIST ( geom ); diff --git a/x/geo/types.go b/x/geo/types.go index f5a886a34c4cf0a52e89109cb02f1bac23532186..d7a0b4171d55f7353cafd6af8b14404083cdec35 100644 --- a/x/geo/types.go +++ b/x/geo/types.go @@ -1,13 +1,31 @@ +/* GENERATED FROM README.org + DO NOT EDIT THIS FILE DIRECTLY!!!!! */ + package geo -type GeometryType int +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type MsgStoreGeo struct { + Data Geometry `json:"data"` + Signer sdk.AccAddress `json:"signer"` +} + +type FeatureType int -//const ( -// Point GeometryType = 0 -// Polygon GeometryType = 1 -//) +const ( + Point FeatureType = 0 + LineString + Polygon + MultiPoint + MultiLineString + MultiPolygon +) type Geometry struct { - //Type GeometryType `json:"type"` - EWKB []byte `json:"ewkb,omitempty"` + Type FeatureType `json:"type"` + // EWKB representation of the geo feature. Must be in the WGS84 coordinate + // system and represent a Point, LineString, Polygon, MultiPoint, MultiLineString or MultiPolygon + EWKB []byte `json:"ewkb,omitempty"` } diff --git a/x/oracle/README.org b/x/oracle/README.org new file mode 100644 index 0000000000000000000000000000000000000000..cfa319f30b7fae8d602b4cf4780159d02beccb40 --- /dev/null +++ b/x/oracle/README.org @@ -0,0 +1,38 @@ +* Consensus Protocol +** Function Invocation +** Function Invocation Request +** Oracle Pool Contract +** Execution Results +** Round Structure +*** Select Oracle +When a compute function invocation is requested against an oracle pool, the first oracle to run the contract is chosen at +random based on the result of the block hash in which the request is transacted. Given an array of ~N~ oracles in an +oracle pool we select the array of the ~M~ oracles which have not been elected to compute this function invocation yet, +maintaining the original array order and call this resulting array the selection pool. The selected oracle is the ~i~'th +oracle in the selection pool array where $i = blockHash \bmod{M}$. A tag alerting the oracle that it has been +selected for this round may be attached to the next block or this information may simply stored in the appropriate index (TODO). +*** Commit Result + Once the selected oracle has completed the requested computation +#+BEGIN_SRC go :tangle types.go + type MsgCommitResult struct { + // The argon2 salted hash of the result, TODO specify parameters + Hash []bytes `json:"bytes"` + Signer sdk.AccAddress `json:"signer"` + } +#+END_SRC +**** Handling Timeouts +The oracle pool contract for the given function will include a timeout window. If the selected oracle cannot complete the +result in the specified timeout window, it should post a heartbeat message before the timeout block and TODO. +If the selected oracle fails to commit a result at all before the end of the timeout window, another oracle will be chosen +at random and the original selection oracle will be marked as unavailable and scheduled for its bond to be slashed accordingly, +unless, of course, all requested oracles timeout in which the curator of the function will be slashed for improper function +implementation. +*** Select Next Oracle or Finish Commit +*** Share Results +*** Vote +#+BEGIN_SRC go :tangle types.go + type MsgVoteResult struct { + Signer sdk.AccAddress `json:"signer"` + } +#+END_SRC +*** Consensus, Resolution Round or Failure diff --git a/x/proposal/README.org b/x/proposal/README.org new file mode 100644 index 0000000000000000000000000000000000000000..0013b836c610056dd3c0597d5b113116455ccc9c --- /dev/null +++ b/x/proposal/README.org @@ -0,0 +1,69 @@ +#+TITLE: Proposal Module +#+BEGIN_SRC sql :tangle proposal.sql :exports none + /* GENERATED FROM README.org + DO NOT EDIT THIS FILE DIRECTLY!!!!! */ + +#+END_SRC + +* Overview + +* Motivation and Rationale + +* Transaction Messages and Types + +#+BEGIN_SRC go +type ProposalID []byte + +type MsgCreateProposal struct { + Proposers []sdk.AccAddress `json:"proposer"` + Agent agent.AgentID + Action ProposalAction `json:"action"` + TryExec bool `json:"try_exec"` +} + +type MsgVote struct { + ID ProposalID `json:"id"` + Voters []sdk.AccAddress `json:"voters"` + Vote bool `json:"vote"` +} + +type MsgTryExecuteProposal struct { + ProposalId []byte `json:"proposal_id"` + Signer sdk.AccAddress `json:"signer"` +} + +type MsgWithdrawProposal struct { + ProposalId []byte `json:"proposal_id"` + Proposer sdk.AccAddress `json:"proposer"` +} + +type Proposal struct { + Proposer sdk.AccAddress `json:"proposer"` + Agent agent.AgentID + Action action.Action `json:"action"` + Approvers []sdk.AccAddress `json:"approvers,omitempty"` +} + +#+END_SRC go + +* Identifiers + +* Indexing and Queries + +** Postgresql +#+BEGIN_SRC sql :tangle proposal.sql + CREATE TABLE proposal ( + uri text NOT NULL PRIMARY KEY, + proposer bytea NOT NULL REFERENCES account, + proposed_at bytea NOT NULL REFERENCES tx, + "action" jsonb NOT NULL + ); + + CREATE TABLE proposal_approvals ( + uri text NOT NULL REFERENCES proposal, + approver bytea NOT NULL REFERENCES account, + voted_at bytea NOT NULL REFERENCES tx + ); +#+END_SRC +** RDF + Proposals aren't indexed in the RDF store. diff --git a/x/schema/README.org b/x/schema/README.org new file mode 100644 index 0000000000000000000000000000000000000000..06e39fc125d441c5b2a50dacdefc4b11c92efce3 --- /dev/null +++ b/x/schema/README.org @@ -0,0 +1,112 @@ +#+TITLE: Schema + +* Overview + +* Motivation and Rationale + +* Transaction Messages and Types + +** Supported Property Types +#+BEGIN_SRC go :tangle types.go + type PropertyType int + + const ( + OBJECT PropertyType = 0 + ENUM + STRING + INTEGER + DECIMAL + BOOL + DOUBLE + DATETIME + DATE + TIME + DURATION + BASE64 + ANYURI + WKT + ) +#+END_SRC + +** Class, Property and Label Integer ID's + Classes, properties and labels receive an auto-incremented integer ID. This ID is used in references in class and property definitions and can also used for saving storage space in a binary RDF serialization format. + +#+BEGIN_SRC go :tangle types.go + type PropertyID uint64 + + type ClassID uint64 + + type LabelID uint64 +#+END_SRC + +** Define Property + +#+BEGIN_SRC go :tangle types.go + type ActionDefineProperty struct { + Agent agent.AgentID `json:"agent"` + Name string `json:"name"` + Many bool `json:"many,omitempty"` + Type PropertyType `json:"type,omitempty"` + Class ClassID `json:"class,omitempty"` + SuperProperties []PropertyID `json:"super_properties,omitempty"` + SubProperties []PropertyID `json:"sub,omitempty"` + EnumLabels []LabelID `json:"enum_labels,omitempty"` + IntegerMin *big.Int `json:"integer_min,omitempty"` + IntegerMax *big.Int `json:"integer_max,omitempty"` + DoubleMin *double `json:"double_min,omitempty"` + DoubleMax *double `json:"double_max,omitempty"` + Label []LangString `json:"label,omitempty"` + Comment []LangString `json:"label,omitempty"` + } + +#+END_SRC + +** Define Class + +#+BEGIN_SRC go :tangle types.go + + type ActionDefineClass struct { + Agent agent.AgentID `json:"agent"` + Name string `json:"name"` + Properties []PropertyRef `json:"properties,omitempty"` + SuperClasses []ClassID `json:"super_classes,omitempty"` + SubClasses []ClassID `json:"sub_classes,omitempty"` + Label []LangString `json:"label,omitempty"` + Comment []LangString `json:"label,omitempty"` + } + + type PropertyRef struct { + Property PropertyID `json:"property"` + Required bool `json:"required,omitempty"` + } + +#+END_SRC + +** Define Label + Labels are IRI's whose sole purpose is to serve as an enum value. + +#+BEGIN_SRC go :tangle types.go + + type ActionDefineLabel struct { + Agent agent.AgentID `json:"agent"` + Name string `json:"name"` + Label []LangString `json:"label,omitempty"` + Comment []LangString `json:"label,omitempty"` + } + +#+END_SRC +** Human-readable labels and descriptions + + Human-readable and localized labels and descriptions can be defined using the ~Label~ and ~Comment~ fields of property and class definitions which map to ~rdfs:label~ and ~rdfs:comment~ properties respectively. Their values like in RDF Schema are an array of ~LangString~'s to support localization. + +#+BEGIN_SRC go :tangle types.go + type LangString struct { + Text String `json:"text,omitempty"` + Language String `json:"lang,omitempty"` + } +#+END_SRC +** TODO bulk insertions +** TODO updates to classes (adding optional properties), human-readable text? + +* Identifiers + Properties and classes are identified by the URI formed by taking the agent URI and appending ~s/~. diff --git a/x/token/README.org b/x/token/README.org new file mode 100644 index 0000000000000000000000000000000000000000..1d2917e193b4a5012b8b66603b646417ff0fe738 --- /dev/null +++ b/x/token/README.org @@ -0,0 +1,23 @@ +#+BEGIN_SRC go +type InitialBalance interface { + Address sdk.AccAddress + Balance sdk.Int +} + +type TokenId []byte + +type TokenKeeper interface { + CreateToken(ctx sdk.Context, denom string, minter sdk.AccAddress, initialBalances []InitialBalance) + GetSupply(ctx sdk.Context, denom string) sdk.Int +} + +type ActionMint interface { + Denom string + Amount sdk.Int + Address sdk.AccAddress +} + +type MintCapability interface { + Denom string +} +#+END_SRC go