From 31aa30082c22139143b9e9617d7245676a856e78 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Thu, 22 Dec 2022 21:16:24 +0900 Subject: [PATCH 01/84] docs: frontpage --- .../images/did-vc.png | Bin .../images/did-vc.xml | 0 .../images/panacea-ecosystem.png | Bin .../images/panacea-ecosystem.xml | 0 .../images/roadmap.png | Bin .../images/tech-stack.png | Bin .../images/tech-stack.xml | 0 .../panacea-ecosystem.md | 0 .../roadmap.md | 0 .../overview.md => 1-users/0-overview.md} | 0 .../1-users/3-data-exchange/0-about-dep.md | 38 ++++++++++++++++++ .../3-data-exchange/1-consume-data.md} | 0 .../1-users/3-data-exchange/2-provide-data.md | 0 .../{dapp-devs => 2-dapp-devs}/overview.md | 0 .../0-overview.md} | 0 .../3-protocol-devs/1-dep-specs/0-overview.md | 19 +++++++++ .../1-dep-specs/1-user-flow.md | 0 .../1-dep-specs/2-data-deal.md | 0 .../1-dep-specs/3-data-exhange-consent.md | 0 .../1-dep-specs/4-data-validation.md | 0 .../1-dep-specs/5-incentives.md | 0 .../1-dep-specs/6-confidential-oracle.md | 0 .../cli-installation.md | 0 .../cosmovisor.md | 0 .../deploy-localnet.md | 0 .gitbook/{validators => 4-validators}/faq.md | 0 .../interaction-with-the-network-cli.md | 4 +- .../join-mainnet-testnet.md | 0 .../ledger-nano.md | 0 .../{validators => 4-validators}/overview.md | 0 .gitbook/5-oracles/overview.md | 0 .gitbook/README.md | 12 +++--- .gitbook/SUMMARY.md | 26 ++++++------ app/export.go | 7 ++-- client/docs/swagger-ui/swagger-ui-bundle.js | 12 +++--- .../swagger-ui-standalone-preset.js | 4 +- client/docs/swagger-ui/swagger.yaml | 38 +++++++++--------- client/docs/swagger_legacy.yaml | 14 +++---- proto/panacea/oracle/v2/query.proto | 4 +- .../cosmos/distribution/v1beta1/query.proto | 8 ++-- .../proto/cosmos/staking/v1beta1/query.proto | 16 ++++---- x/oracle/client/cli/queryOracle.go | 6 +-- x/oracle/types/genesis.pb.go | 2 +- x/oracle/types/oracle.pb.go | 6 +-- x/oracle/types/query.pb.go | 6 +-- x/oracle/types/query.pb.gw.go | 4 +- 46 files changed, 142 insertions(+), 84 deletions(-) rename .gitbook/{about-panacea => 0-about-panacea}/images/did-vc.png (100%) rename .gitbook/{about-panacea => 0-about-panacea}/images/did-vc.xml (100%) rename .gitbook/{about-panacea => 0-about-panacea}/images/panacea-ecosystem.png (100%) rename .gitbook/{about-panacea => 0-about-panacea}/images/panacea-ecosystem.xml (100%) rename .gitbook/{about-panacea => 0-about-panacea}/images/roadmap.png (100%) rename .gitbook/{about-panacea => 0-about-panacea}/images/tech-stack.png (100%) rename .gitbook/{about-panacea => 0-about-panacea}/images/tech-stack.xml (100%) rename .gitbook/{about-panacea => 0-about-panacea}/panacea-ecosystem.md (100%) rename .gitbook/{about-panacea => 0-about-panacea}/roadmap.md (100%) rename .gitbook/{users/overview.md => 1-users/0-overview.md} (100%) create mode 100644 .gitbook/1-users/3-data-exchange/0-about-dep.md rename .gitbook/{oracles/overview.md => 1-users/3-data-exchange/1-consume-data.md} (100%) create mode 100644 .gitbook/1-users/3-data-exchange/2-provide-data.md rename .gitbook/{dapp-devs => 2-dapp-devs}/overview.md (100%) rename .gitbook/{protocol-devs/overview.md => 3-protocol-devs/0-overview.md} (100%) create mode 100644 .gitbook/3-protocol-devs/1-dep-specs/0-overview.md create mode 100644 .gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md create mode 100644 .gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md create mode 100644 .gitbook/3-protocol-devs/1-dep-specs/3-data-exhange-consent.md create mode 100644 .gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md create mode 100644 .gitbook/3-protocol-devs/1-dep-specs/5-incentives.md create mode 100644 .gitbook/3-protocol-devs/1-dep-specs/6-confidential-oracle.md rename .gitbook/{validators => 4-validators}/cli-installation.md (100%) rename .gitbook/{validators => 4-validators}/cosmovisor.md (100%) rename .gitbook/{validators => 4-validators}/deploy-localnet.md (100%) rename .gitbook/{validators => 4-validators}/faq.md (100%) rename .gitbook/{validators => 4-validators}/interaction-with-the-network-cli.md (99%) rename .gitbook/{validators => 4-validators}/join-mainnet-testnet.md (100%) rename .gitbook/{validators => 4-validators}/ledger-nano.md (100%) rename .gitbook/{validators => 4-validators}/overview.md (100%) create mode 100644 .gitbook/5-oracles/overview.md diff --git a/.gitbook/about-panacea/images/did-vc.png b/.gitbook/0-about-panacea/images/did-vc.png similarity index 100% rename from .gitbook/about-panacea/images/did-vc.png rename to .gitbook/0-about-panacea/images/did-vc.png diff --git a/.gitbook/about-panacea/images/did-vc.xml b/.gitbook/0-about-panacea/images/did-vc.xml similarity index 100% rename from .gitbook/about-panacea/images/did-vc.xml rename to .gitbook/0-about-panacea/images/did-vc.xml diff --git a/.gitbook/about-panacea/images/panacea-ecosystem.png b/.gitbook/0-about-panacea/images/panacea-ecosystem.png similarity index 100% rename from .gitbook/about-panacea/images/panacea-ecosystem.png rename to .gitbook/0-about-panacea/images/panacea-ecosystem.png diff --git a/.gitbook/about-panacea/images/panacea-ecosystem.xml b/.gitbook/0-about-panacea/images/panacea-ecosystem.xml similarity index 100% rename from .gitbook/about-panacea/images/panacea-ecosystem.xml rename to .gitbook/0-about-panacea/images/panacea-ecosystem.xml diff --git a/.gitbook/about-panacea/images/roadmap.png b/.gitbook/0-about-panacea/images/roadmap.png similarity index 100% rename from .gitbook/about-panacea/images/roadmap.png rename to .gitbook/0-about-panacea/images/roadmap.png diff --git a/.gitbook/about-panacea/images/tech-stack.png b/.gitbook/0-about-panacea/images/tech-stack.png similarity index 100% rename from .gitbook/about-panacea/images/tech-stack.png rename to .gitbook/0-about-panacea/images/tech-stack.png diff --git a/.gitbook/about-panacea/images/tech-stack.xml b/.gitbook/0-about-panacea/images/tech-stack.xml similarity index 100% rename from .gitbook/about-panacea/images/tech-stack.xml rename to .gitbook/0-about-panacea/images/tech-stack.xml diff --git a/.gitbook/about-panacea/panacea-ecosystem.md b/.gitbook/0-about-panacea/panacea-ecosystem.md similarity index 100% rename from .gitbook/about-panacea/panacea-ecosystem.md rename to .gitbook/0-about-panacea/panacea-ecosystem.md diff --git a/.gitbook/about-panacea/roadmap.md b/.gitbook/0-about-panacea/roadmap.md similarity index 100% rename from .gitbook/about-panacea/roadmap.md rename to .gitbook/0-about-panacea/roadmap.md diff --git a/.gitbook/users/overview.md b/.gitbook/1-users/0-overview.md similarity index 100% rename from .gitbook/users/overview.md rename to .gitbook/1-users/0-overview.md diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md new file mode 100644 index 00000000..3aba7f3f --- /dev/null +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -0,0 +1,38 @@ +# About Data Exchange Protocol + +Data Exchange Protocol (hereafter 'DEP') is a communication layer for sharing and exchanging various types of data +between two parties in decentralized environments. + + +## tl;dr + +Data consumers can open data deals by specifying what type of data and how much they want, and how much they can pay for it. + +Data providers can choose deals that match the data they have and they are willing to provide. + +To guarantee data consumers can only consume data in the form they want, +decentralized oracles verify and issue certificates for all data being shared + +Panacea public blockchain manages the status of all data deals and data sharing consents, +ensuring data providers and ecosystem operators are rewarded appropriately. + + +## Motivation and Goals + +### Data Ownership and Sovereignty + +The ultimate goal of owning our own data is having a control about how our data is used. + +### Decentralized off-chain data validation + +To ensure data consumers can only consume data that they want, all data being shared must be validated by +decentralized players who are not malicious. + +### Privacy + +Throughout the entire process of data verification and transmission, +the data content must not be exposed to anyone other than the consumer intended by the data provider. + +### Generalized data exchange + +Not only healthcare data, but various types of data should be covered through this protocol. diff --git a/.gitbook/oracles/overview.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md similarity index 100% rename from .gitbook/oracles/overview.md rename to .gitbook/1-users/3-data-exchange/1-consume-data.md diff --git a/.gitbook/1-users/3-data-exchange/2-provide-data.md b/.gitbook/1-users/3-data-exchange/2-provide-data.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/dapp-devs/overview.md b/.gitbook/2-dapp-devs/overview.md similarity index 100% rename from .gitbook/dapp-devs/overview.md rename to .gitbook/2-dapp-devs/overview.md diff --git a/.gitbook/protocol-devs/overview.md b/.gitbook/3-protocol-devs/0-overview.md similarity index 100% rename from .gitbook/protocol-devs/overview.md rename to .gitbook/3-protocol-devs/0-overview.md diff --git a/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md b/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md new file mode 100644 index 00000000..883332d5 --- /dev/null +++ b/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md @@ -0,0 +1,19 @@ +# Data Exchange Protocol Specifications + +Prior to diving into the technical specifications of Data Exchange Protocol (hereafter 'DEP'), +we recommend you to understand what DEP is, its motivation, and goals from the [About DEP](../../1-users/3-data-exchange/0-about-dep.md) documentation. + +## Protocol Specifications + +In the following sections, you can find detailed protocol specifications including technical architectures, message formats, +hardware requirements, and core implementation details. + +According to these specifications, protocol developers can make implementations +based on various programming languages and infrastructure. + +1. [User Flow](1-user-flow.md) +2. [Data Deal](2-data-deal.md) +3. [Data Exchange Consent](3-data-exhange-consent.md) +4. [Data Validation](4-data-validation.md) +5. [Incentives](5-incentives.md) +6. [Confidential Oracle](6-confidential-oracle.md) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/3-protocol-devs/1-dep-specs/3-data-exhange-consent.md b/.gitbook/3-protocol-devs/1-dep-specs/3-data-exhange-consent.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md b/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/3-protocol-devs/1-dep-specs/5-incentives.md b/.gitbook/3-protocol-devs/1-dep-specs/5-incentives.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/3-protocol-devs/1-dep-specs/6-confidential-oracle.md b/.gitbook/3-protocol-devs/1-dep-specs/6-confidential-oracle.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/validators/cli-installation.md b/.gitbook/4-validators/cli-installation.md similarity index 100% rename from .gitbook/validators/cli-installation.md rename to .gitbook/4-validators/cli-installation.md diff --git a/.gitbook/validators/cosmovisor.md b/.gitbook/4-validators/cosmovisor.md similarity index 100% rename from .gitbook/validators/cosmovisor.md rename to .gitbook/4-validators/cosmovisor.md diff --git a/.gitbook/validators/deploy-localnet.md b/.gitbook/4-validators/deploy-localnet.md similarity index 100% rename from .gitbook/validators/deploy-localnet.md rename to .gitbook/4-validators/deploy-localnet.md diff --git a/.gitbook/validators/faq.md b/.gitbook/4-validators/faq.md similarity index 100% rename from .gitbook/validators/faq.md rename to .gitbook/4-validators/faq.md diff --git a/.gitbook/validators/interaction-with-the-network-cli.md b/.gitbook/4-validators/interaction-with-the-network-cli.md similarity index 99% rename from .gitbook/validators/interaction-with-the-network-cli.md rename to .gitbook/4-validators/interaction-with-the-network-cli.md index 033c56b9..98353436 100644 --- a/.gitbook/validators/interaction-with-the-network-cli.md +++ b/.gitbook/4-validators/interaction-with-the-network-cli.md @@ -308,7 +308,7 @@ In other words, validators cannot be in the active set, if their total stake (= You can confirm that you are in the validator set by the following command: ```bash -panacead query staking validators +panacead query staking 4-validators ``` ### Edit validator description @@ -351,7 +351,7 @@ You can delegate `umed` to a validator. These delegators can receive part of the You can query the list of all validators of a specific chain: ```bash -panacead query staking validators +panacead query staking 4-validators ``` If you want to get the information of a single validator you can check it with: diff --git a/.gitbook/validators/join-mainnet-testnet.md b/.gitbook/4-validators/join-mainnet-testnet.md similarity index 100% rename from .gitbook/validators/join-mainnet-testnet.md rename to .gitbook/4-validators/join-mainnet-testnet.md diff --git a/.gitbook/validators/ledger-nano.md b/.gitbook/4-validators/ledger-nano.md similarity index 100% rename from .gitbook/validators/ledger-nano.md rename to .gitbook/4-validators/ledger-nano.md diff --git a/.gitbook/validators/overview.md b/.gitbook/4-validators/overview.md similarity index 100% rename from .gitbook/validators/overview.md rename to .gitbook/4-validators/overview.md diff --git a/.gitbook/5-oracles/overview.md b/.gitbook/5-oracles/overview.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/README.md b/.gitbook/README.md index a5dd5ca8..83c9bec3 100644 --- a/.gitbook/README.md +++ b/.gitbook/README.md @@ -1,8 +1,8 @@ # MediBloc Panacea Documentation -- [About Panacea](about-panacea/panacea-ecosystem.md) -- [For Users](users/overview.md) -- [For dApp Developers](dapp-devs/overview.md) -- [For Protocol Developers](protocol-devs/overview.md) -- [For Validators](validators/overview.md) -- [For Oracles](oracles/overview.md) +- [About Panacea](0-about-panacea/panacea-ecosystem.md) +- [For Users](1-users/0-overview.md) +- [For dApp Developers](2-dapp-devs/overview.md) +- [For Protocol Developers](3-protocol-devs/0-overview.md) +- [For Validators](4-validators/overview.md) +- [For Oracles](5-oracles/overview.md) diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index 0e666e7d..c7a8a0ca 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -2,12 +2,12 @@ ## Overview -* [Panacea Ecosystem](about-panacea/panacea-ecosystem.md) -* [Roadmap](about-panacea/roadmap.md) +* [Panacea Ecosystem](0-about-panacea/panacea-ecosystem.md) +* [Roadmap](0-about-panacea/roadmap.md) ## For Users -* [Overview](users/overview.md) +* [Overview](1-users/0-overview.md) * Basic Concepts * MED * Transactions, Gas & Fees @@ -27,34 +27,34 @@ ## For dApp Devs -* [Overview](dapp-devs/overview.md) +* [Overview](2-dapp-devs/overview.md) * Endpoints * Client Libraries ## For Protocol Devs -* [Overview](protocol-devs/overview.md) +* [Overview](3-protocol-devs/0-overview.md) * Data Exchange Protocol Specs * Modules * Dev Guides ## For Validators -* [Overview](validators/overview.md) -* [CLI Installation](validators/cli-installation.md) -* [Deploy Localnet](validators/deploy-localnet.md) -* [Join Mainnet/Testnet](validators/join-mainnet-testnet.md) -* [Cosmovisor](validators/cosmovisor.md) +* [Overview](4-validators/overview.md) +* [CLI Installation](4-validators/cli-installation.md) +* [Deploy Localnet](4-validators/deploy-localnet.md) +* [Join Mainnet/Testnet](4-validators/join-mainnet-testnet.md) +* [Cosmovisor](4-validators/cosmovisor.md) * Security * Sentry Nodes * Validator Backup - * [Ledger Nano](validators/ledger-nano.md) + * [Ledger Nano](4-validators/ledger-nano.md) * Software Upgrade Guide -* [FAQ](validators/faq.md) +* [FAQ](4-validators/faq.md) ## For Oracles -* [Overview](oracles/overview.md) +* [Overview](5-oracles/overview.md) * Data Exchange Protocol * Concepts * Oracle diff --git a/app/export.go b/app/export.go index a744e549..87dc48b1 100644 --- a/app/export.go +++ b/app/export.go @@ -50,7 +50,8 @@ func (app *App) ExportAppStateAndValidators( // prepare for fresh start at zero height // NOTE zero height genesis is a temporary feature which will be deprecated -// in favour of export at a block height +// +// in favour of export at a block height func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) { applyAllowedAddrs := false @@ -102,7 +103,7 @@ func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []str height := ctx.BlockHeight() ctx = ctx.WithBlockHeight(0) - // reinitialize all validators + // reinitialize all 4-validators app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) { // donate any unwithdrawn outstanding reward fraction tokens to the community pool scraps := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, val.GetOperator()) @@ -143,7 +144,7 @@ func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []str return false }) - // Iterate through validators by power descending, reset bond heights, and + // Iterate through 4-validators by power descending, reset bond heights, and // update bond intra-tx counters. store := ctx.KVStore(app.keys[stakingtypes.StoreKey]) iter := sdk.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey) diff --git a/client/docs/swagger-ui/swagger-ui-bundle.js b/client/docs/swagger-ui/swagger-ui-bundle.js index eb17452a..bb1049c0 100644 --- a/client/docs/swagger-ui/swagger-ui-bundle.js +++ b/client/docs/swagger-ui/swagger-ui-bundle.js @@ -22746,7 +22746,7 @@ function h(e) { function n(n, r, i, a, s, l, f) { - (a = a || c, l = l || i, f !== u) && (t && o(!1, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types")); + (a = a || c, l = l || i, f !== u) && (t && o(!1, "Calling PropTypes 4-validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types")); return null == r[i] ? n ? null === r[i] ? new d("The " + s + " `" + l + "` is marked as required in `" + a + "`, but its value is `null`.") : new d("The " + s + " `" + l + "` is marked as required in `" + a + "`, but its value is `undefined`.") : null : e(r, i, a, s, l) } var r = n.bind(null, !1); @@ -31027,7 +31027,7 @@ i = n(269); e.exports = function() { function e(e, t, n, r, a, u) { - u !== i && o(!1, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types") + u !== i && o(!1, "Calling PropTypes 4-validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types") } function t() { @@ -36904,18 +36904,18 @@ i = t.taggedOperations(), a = o("Collapse"); return s.default.createElement("div", null, s.default.createElement("h4", { - className: "about-panacea-title" + className: "0-about-panacea-title" }, "Overview"), i.map(function(e, t) { var o = e.get("operations"), - i = ["about-panacea-tags", t], + i = ["0-about-panacea-tags", t], u = n.isShown(i, !0); return s.default.createElement("div", { - key: "about-panacea-" + t + key: "0-about-panacea-" + t }, s.default.createElement("h4", { onClick: function() { return r.show(i, !u) }, - className: "link about-panacea-tag" + className: "link 0-about-panacea-tag" }, " ", u ? "-" : "+", t), s.default.createElement(a, { isOpened: u, animated: !0 diff --git a/client/docs/swagger-ui/swagger-ui-standalone-preset.js b/client/docs/swagger-ui/swagger-ui-standalone-preset.js index f4e8b1a1..2e218ec1 100644 --- a/client/docs/swagger-ui/swagger-ui-standalone-preset.js +++ b/client/docs/swagger-ui/swagger-ui-standalone-preset.js @@ -8627,7 +8627,7 @@ function d(t) { function n(n, r, o, u, s, c, l) { - (u = u || f, c = c || o, l !== a) && (e && i(!1, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types")); + (u = u || f, c = c || o, l !== a) && (e && i(!1, "Calling PropTypes 4-validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types")); return null == r[o] ? n ? null === r[o] ? new h("The " + s + " `" + c + "` is marked as required in `" + u + "`, but its value is `null`.") : new h("The " + s + " `" + c + "` is marked as required in `" + u + "`, but its value is `undefined`.") : null : t(r, o, u, s, c) } var r = n.bind(null, !1); @@ -8897,7 +8897,7 @@ o = n(164); t.exports = function() { function t(t, e, n, r, u, a) { - a !== o && i(!1, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types") + a !== o && i(!1, "Calling PropTypes 4-validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types") } function e() { diff --git a/client/docs/swagger-ui/swagger.yaml b/client/docs/swagger-ui/swagger.yaml index 7dfd809c..d9fabdf9 100644 --- a/client/docs/swagger-ui/swagger.yaml +++ b/client/docs/swagger-ui/swagger.yaml @@ -2054,7 +2054,7 @@ paths: x-example: cosmos16xyempempp92x9hyzz9wrgf94r6j9h5f06pxxv get: deprecated: true - summary: Query all validators that a delegator is bonded to + summary: Query all 4-validators that a delegator is bonded to tags: - Staking produces: @@ -2531,8 +2531,8 @@ paths: /slashing/signing_infos: get: deprecated: true - summary: Get sign info of given all validators - description: Get sign info of all validators + summary: Get sign info of given all 4-validators + description: Get sign info of all 4-validators produces: - application/json tags: @@ -2567,7 +2567,7 @@ paths: missed_blocks_counter: type: string '400': - description: Invalid validator public key for one of the validators + description: Invalid validator public key for one of the 4-validators '500': description: Internal Server Error '/slashing/validators/{validatorAddr}/unjail': @@ -3011,7 +3011,7 @@ paths: x-example: Param Change description: type: string - x-example: Update max validators + x-example: Update max 4-validators proposer: type: string description: bech32 encoded address @@ -8904,7 +8904,7 @@ paths: - Query '/cosmos/distribution/v1beta1/delegators/{delegator_address}/validators': get: - summary: DelegatorValidators queries the validators of a delegator. + summary: DelegatorValidators queries the 4-validators of a delegator. operationId: DelegatorValidators responses: '200': @@ -13067,7 +13067,7 @@ paths: - Query /cosmos/slashing/v1beta1/signing_infos: get: - summary: SigningInfos queries signing info of all validators + summary: SigningInfos queries signing info of all 4-validators operationId: SigningInfos responses: '200': @@ -13115,7 +13115,7 @@ paths: monitoring their liveness activity. - title: info is the signing info of all validators + title: info is the signing info of all 4-validators pagination: type: object properties: @@ -14693,7 +14693,7 @@ paths: bonded shares multiplied by exchange rate. - description: validators defines the the validators' info of a delegator. + description: 4-validators defines the the 4-validators' info of a delegator. pagination: description: pagination defines the pagination in the response. type: object @@ -16113,7 +16113,7 @@ paths: max_validators: type: integer format: int64 - description: max_validators is the maximum number of validators. + description: max_validators is the maximum number of 4-validators. max_entries: type: integer format: int64 @@ -16540,7 +16540,7 @@ paths: - Query /cosmos/staking/v1beta1/validators: get: - summary: Validators queries all validators that match the given status. + summary: Validators queries all 4-validators that match the given status. operationId: Validators responses: '200': @@ -16861,7 +16861,7 @@ paths: bonded shares multiplied by exchange rate. - description: validators contains all the queried validators. + description: 4-validators contains all the queried 4-validators. pagination: description: pagination defines the pagination in the response. type: object @@ -17074,7 +17074,7 @@ paths: } parameters: - name: status - description: status enables to query for validators matching a given status. + description: status enables to query for 4-validators matching a given status. in: query required: false type: string @@ -36774,7 +36774,7 @@ definitions: type: array items: type: string - description: validators defines the validators a delegator is delegating for. + description: 4-validators defines the 4-validators a delegator is delegating for. description: |- QueryDelegatorValidatorsResponse is the response type for the Query/DelegatorValidators RPC method. @@ -38689,7 +38689,7 @@ definitions: monitoring their liveness activity. - title: info is the signing info of all validators + title: info is the signing info of all 4-validators pagination: type: object properties: @@ -39281,7 +39281,7 @@ definitions: max_validators: type: integer format: int64 - description: max_validators is the maximum number of validators. + description: max_validators is the maximum number of 4-validators. max_entries: type: integer format: int64 @@ -40100,7 +40100,7 @@ definitions: exchange rate. Voting power can be calculated as total bonded shares multiplied by exchange rate. - description: validators defines the the validators' info of a delegator. + description: 4-validators defines the the 4-validators' info of a delegator. pagination: description: pagination defines the pagination in the response. type: object @@ -40526,7 +40526,7 @@ definitions: max_validators: type: integer format: int64 - description: max_validators is the maximum number of validators. + description: max_validators is the maximum number of 4-validators. max_entries: type: integer format: int64 @@ -41472,7 +41472,7 @@ definitions: exchange rate. Voting power can be calculated as total bonded shares multiplied by exchange rate. - description: validators contains all the queried validators. + description: 4-validators contains all the queried 4-validators. pagination: description: pagination defines the pagination in the response. type: object diff --git a/client/docs/swagger_legacy.yaml b/client/docs/swagger_legacy.yaml index fe00efa4..8a6d3169 100644 --- a/client/docs/swagger_legacy.yaml +++ b/client/docs/swagger_legacy.yaml @@ -754,7 +754,7 @@ paths: x-example: cosmos16xyempempp92x9hyzz9wrgf94r6j9h5f06pxxv get: deprecated: true - summary: Query all validators that a delegator is bonded to + summary: Query all 4-validators that a delegator is bonded to tags: - Staking produces: @@ -803,7 +803,7 @@ paths: /staking/validators: get: deprecated: true - summary: Get all validator candidates. By default it returns only the bonded validators. + summary: Get all validator candidates. By default it returns only the bonded 4-validators. parameters: - in: query name: status @@ -968,7 +968,7 @@ paths: 500: description: Internal Server Error # TODO: We need to either fix this route when the validator is not found or add a slashed validator in the contract tests - # /slashing/validators/{validatorPubKey}/signing_info: + # /slashing/4-validators/{validatorPubKey}/signing_info: # get: # summary: Get sign info of given validator # description: Get sign info of given validator @@ -995,8 +995,8 @@ paths: /slashing/signing_infos: get: deprecated: true - summary: Get sign info of given all validators - description: Get sign info of all validators + summary: Get sign info of given all 4-validators + description: Get sign info of all 4-validators produces: - application/json tags: @@ -1022,7 +1022,7 @@ paths: items: $ref: "#/definitions/SigningInfo" 400: - description: Invalid validator public key for one of the validators + description: Invalid validator public key for one of the 4-validators 500: description: Internal Server Error /slashing/validators/{validatorAddr}/unjail: @@ -1195,7 +1195,7 @@ paths: x-example: "Param Change" description: type: string - x-example: "Update max validators" + x-example: "Update max 4-validators" proposer: $ref: "#/definitions/Address" deposit: diff --git a/proto/panacea/oracle/v2/query.proto b/proto/panacea/oracle/v2/query.proto index 436b12ae..86580e3d 100644 --- a/proto/panacea/oracle/v2/query.proto +++ b/proto/panacea/oracle/v2/query.proto @@ -14,12 +14,12 @@ import "panacea/oracle/v2/genesis.proto"; service Query { // Oracles returns a list of oracles. rpc Oracles(QueryOraclesRequest) returns (QueryOraclesResponse) { - option (google.api.http).get = "/panacea/oracle/v2/oracles"; + option (google.api.http).get = "/panacea/oracle/v2/5-oracles"; } // Oracle returns a oracle. rpc Oracle(QueryOracleRequest) returns (QueryOracleResponse) { - option (google.api.http).get = "/panacea/oracle/v2/oracles/{oracle_address}"; + option (google.api.http).get = "/panacea/oracle/v2/5-oracles/{oracle_address}"; } // OracleRegistrations returns a list of OracleRegistration. diff --git a/third_party/proto/cosmos/distribution/v1beta1/query.proto b/third_party/proto/cosmos/distribution/v1beta1/query.proto index 2991218d..cb9b1839 100644 --- a/third_party/proto/cosmos/distribution/v1beta1/query.proto +++ b/third_party/proto/cosmos/distribution/v1beta1/query.proto @@ -19,19 +19,19 @@ service Query { // ValidatorOutstandingRewards queries rewards of a validator address. rpc ValidatorOutstandingRewards(QueryValidatorOutstandingRewardsRequest) returns (QueryValidatorOutstandingRewardsResponse) { - option (google.api.http).get = "/cosmos/distribution/v1beta1/validators/" + option (google.api.http).get = "/cosmos/distribution/v1beta1/4-validators/" "{validator_address}/outstanding_rewards"; } // ValidatorCommission queries accumulated commission for a validator. rpc ValidatorCommission(QueryValidatorCommissionRequest) returns (QueryValidatorCommissionResponse) { - option (google.api.http).get = "/cosmos/distribution/v1beta1/validators/" + option (google.api.http).get = "/cosmos/distribution/v1beta1/4-validators/" "{validator_address}/commission"; } // ValidatorSlashes queries slash events of a validator. rpc ValidatorSlashes(QueryValidatorSlashesRequest) returns (QueryValidatorSlashesResponse) { - option (google.api.http).get = "/cosmos/distribution/v1beta1/validators/{validator_address}/slashes"; + option (google.api.http).get = "/cosmos/distribution/v1beta1/4-validators/{validator_address}/slashes"; } // DelegationRewards queries the total rewards accrued by a delegation. @@ -49,7 +49,7 @@ service Query { // DelegatorValidators queries the validators of a delegator. rpc DelegatorValidators(QueryDelegatorValidatorsRequest) returns (QueryDelegatorValidatorsResponse) { option (google.api.http).get = "/cosmos/distribution/v1beta1/delegators/" - "{delegator_address}/validators"; + "{delegator_address}/4-validators"; } // DelegatorWithdrawAddress queries withdraw address of a delegator. diff --git a/third_party/proto/cosmos/staking/v1beta1/query.proto b/third_party/proto/cosmos/staking/v1beta1/query.proto index 4852c535..42db4254 100644 --- a/third_party/proto/cosmos/staking/v1beta1/query.proto +++ b/third_party/proto/cosmos/staking/v1beta1/query.proto @@ -12,36 +12,36 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/staking/types"; service Query { // Validators queries all validators that match the given status. rpc Validators(QueryValidatorsRequest) returns (QueryValidatorsResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/validators"; + option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators"; } // Validator queries validator info for given validator address. rpc Validator(QueryValidatorRequest) returns (QueryValidatorResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/validators/{validator_addr}"; + option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/{validator_addr}"; } // ValidatorDelegations queries delegate info for given validator. rpc ValidatorDelegations(QueryValidatorDelegationsRequest) returns (QueryValidatorDelegationsResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/validators/{validator_addr}/delegations"; + option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/{validator_addr}/delegations"; } // ValidatorUnbondingDelegations queries unbonding delegations of a validator. rpc ValidatorUnbondingDelegations(QueryValidatorUnbondingDelegationsRequest) returns (QueryValidatorUnbondingDelegationsResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/validators/" + option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/" "{validator_addr}/unbonding_delegations"; } // Delegation queries delegate info for given validator delegator pair. rpc Delegation(QueryDelegationRequest) returns (QueryDelegationResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/" + option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/{validator_addr}/delegations/" "{delegator_addr}"; } // UnbondingDelegation queries unbonding info for given validator delegator // pair. rpc UnbondingDelegation(QueryUnbondingDelegationRequest) returns (QueryUnbondingDelegationResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/" + option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/{validator_addr}/delegations/" "{delegator_addr}/unbonding_delegation"; } @@ -66,13 +66,13 @@ service Query { // DelegatorValidators queries all validators info for given delegator // address. rpc DelegatorValidators(QueryDelegatorValidatorsRequest) returns (QueryDelegatorValidatorsResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators"; + option (google.api.http).get = "/cosmos/staking/v1beta1/delegators/{delegator_addr}/4-validators"; } // DelegatorValidator queries validator info for given delegator validator // pair. rpc DelegatorValidator(QueryDelegatorValidatorRequest) returns (QueryDelegatorValidatorResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators/" + option (google.api.http).get = "/cosmos/staking/v1beta1/delegators/{delegator_addr}/4-validators/" "{validator_addr}"; } diff --git a/x/oracle/client/cli/queryOracle.go b/x/oracle/client/cli/queryOracle.go index ae792ace..5331e424 100644 --- a/x/oracle/client/cli/queryOracle.go +++ b/x/oracle/client/cli/queryOracle.go @@ -9,8 +9,8 @@ import ( func CmdGetOracles() *cobra.Command { cmd := &cobra.Command{ - Use: "oracles", - Short: "Query oracles info", + Use: "5-oracles", + Short: "Query 5-oracles info", RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { @@ -37,7 +37,7 @@ func CmdGetOracles() *cobra.Command { } flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "oracles") + flags.AddPaginationFlagsToCmd(cmd, "5-oracles") return cmd } diff --git a/x/oracle/types/genesis.pb.go b/x/oracle/types/genesis.pb.go index e36006ed..3134bff0 100644 --- a/x/oracle/types/genesis.pb.go +++ b/x/oracle/types/genesis.pb.go @@ -26,7 +26,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the oracle module's genesis state. type GenesisState struct { - Oracles []Oracle `protobuf:"bytes,1,rep,name=oracles,proto3" json:"oracles"` + Oracles []Oracle `protobuf:"bytes,1,rep,name=5-oracles,proto3" json:"5-oracles"` OracleRegistrations []OracleRegistration `protobuf:"bytes,2,rep,name=oracle_registrations,json=oracleRegistrations,proto3" json:"oracle_registrations"` Params Params `protobuf:"bytes,3,opt,name=params,proto3" json:"params"` } diff --git a/x/oracle/types/oracle.pb.go b/x/oracle/types/oracle.pb.go index 1d9ff844..ca9dba92 100644 --- a/x/oracle/types/oracle.pb.go +++ b/x/oracle/types/oracle.pb.go @@ -105,14 +105,14 @@ type OracleRegistration struct { UniqueId string `protobuf:"bytes,1,opt,name=unique_id,json=uniqueId,proto3" json:"unique_id,omitempty"` OracleAddress string `protobuf:"bytes,2,opt,name=oracle_address,json=oracleAddress,proto3" json:"oracle_address,omitempty"` // Node public key is a pair with a node private key which is generated in SGX by each oracle. - // This key is used to share the oracle private key from other oracles. + // This key is used to share the oracle private key from other 5-oracles. NodePubKey []byte `protobuf:"bytes,3,opt,name=node_pub_key,json=nodePubKey,proto3" json:"node_pub_key,omitempty"` // Anyone can validate that the node key pair is generated in SGX using this node key remote report. NodePubKeyRemoteReport []byte `protobuf:"bytes,4,opt,name=node_pub_key_remote_report,json=nodePubKeyRemoteReport,proto3" json:"node_pub_key_remote_report,omitempty"` // A newly joining oracle must report a trusted block info which was used to initialize its light client. - // Other oracles will validate whether this trusted block info is correct, + // Other 5-oracles will validate whether this trusted block info is correct, // in order to prevent malicious operators from making the oracle look at a malicious chain node. - // Other oracles don't have to worry about whether this block info was set by a malicious operator, + // Other 5-oracles don't have to worry about whether this block info was set by a malicious operator, // because this message has to be generated inside SGX. // Also, after this oracle registration is complete, the light client is protected from malicious operators by SGX. TrustedBlockHeight int64 `protobuf:"varint,5,opt,name=trusted_block_height,json=trustedBlockHeight,proto3" json:"trusted_block_height,omitempty"` diff --git a/x/oracle/types/query.pb.go b/x/oracle/types/query.pb.go index 8aea2f34..fe21ab7e 100644 --- a/x/oracle/types/query.pb.go +++ b/x/oracle/types/query.pb.go @@ -78,7 +78,7 @@ func (m *QueryOraclesRequest) GetPagination() *query.PageRequest { // QueryOracleResponse is the response type for the Query/Oracles RPC method. type QueryOraclesResponse struct { - Oracles []*Oracle `protobuf:"bytes,1,rep,name=oracles,proto3" json:"oracles,omitempty"` + Oracles []*Oracle `protobuf:"bytes,1,rep,name=5-oracles,proto3" json:"5-oracles,omitempty"` Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` } @@ -579,7 +579,7 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type QueryClient interface { - // Oracles returns a list of oracles. + // Oracles returns a list of 5-oracles. Oracles(ctx context.Context, in *QueryOraclesRequest, opts ...grpc.CallOption) (*QueryOraclesResponse, error) // Oracle returns a oracle. Oracle(ctx context.Context, in *QueryOracleRequest, opts ...grpc.CallOption) (*QueryOracleResponse, error) @@ -646,7 +646,7 @@ func (c *queryClient) Params(ctx context.Context, in *QueryOracleParamsRequest, // QueryServer is the server API for Query service. type QueryServer interface { - // Oracles returns a list of oracles. + // Oracles returns a list of 5-oracles. Oracles(context.Context, *QueryOraclesRequest) (*QueryOraclesResponse, error) // Oracle returns a oracle. Oracle(context.Context, *QueryOracleRequest) (*QueryOracleResponse, error) diff --git a/x/oracle/types/query.pb.gw.go b/x/oracle/types/query.pb.gw.go index 74beaae5..c39ff91b 100644 --- a/x/oracle/types/query.pb.gw.go +++ b/x/oracle/types/query.pb.gw.go @@ -538,9 +538,9 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Oracles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"panacea", "oracle", "v2", "oracles"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Oracles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"panacea", "oracle", "v2", "5-oracles"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_Oracle_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"panacea", "oracle", "v2", "oracles", "oracle_address"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Oracle_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"panacea", "oracle", "v2", "5-oracles", "oracle_address"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_OracleRegistrations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"panacea", "oracle", "v2", "oracle-registrations", "unique_id"}, "", runtime.AssumeColonVerbOpt(true))) From 23b23992ba181c4391b42d952be9904b074fc8e8 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Thu, 22 Dec 2022 21:23:41 +0900 Subject: [PATCH 02/84] fix --- .gitbook/1-users/3-data-exchange/0-about-dep.md | 5 +++++ .gitbook/3-protocol-devs/1-dep-specs/0-overview.md | 8 ++++---- ...xhange-consent.md => 3-data-provider-consent.md} | 0 .../{5-incentives.md => 5-confidential-oracle.md} | 0 .../{6-confidential-oracle.md => 6-incentives.md} | 0 .gitbook/SUMMARY.md | 13 ++++++++++--- 6 files changed, 19 insertions(+), 7 deletions(-) rename .gitbook/3-protocol-devs/1-dep-specs/{3-data-exhange-consent.md => 3-data-provider-consent.md} (100%) rename .gitbook/3-protocol-devs/1-dep-specs/{5-incentives.md => 5-confidential-oracle.md} (100%) rename .gitbook/3-protocol-devs/1-dep-specs/{6-confidential-oracle.md => 6-incentives.md} (100%) diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md index 3aba7f3f..80549af7 100644 --- a/.gitbook/1-users/3-data-exchange/0-about-dep.md +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -36,3 +36,8 @@ the data content must not be exposed to anyone other than the consumer intended ### Generalized data exchange Not only healthcare data, but various types of data should be covered through this protocol. + +### Open-sourced protocol + +All protocol specifications and implementations must be open-sourced, so any participants can understand +how data is exchanged and how privacy is guaranteed. \ No newline at end of file diff --git a/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md b/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md index 883332d5..0e23c72f 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md @@ -3,7 +3,7 @@ Prior to diving into the technical specifications of Data Exchange Protocol (hereafter 'DEP'), we recommend you to understand what DEP is, its motivation, and goals from the [About DEP](../../1-users/3-data-exchange/0-about-dep.md) documentation. -## Protocol Specifications +## Specifications In the following sections, you can find detailed protocol specifications including technical architectures, message formats, hardware requirements, and core implementation details. @@ -13,7 +13,7 @@ based on various programming languages and infrastructure. 1. [User Flow](1-user-flow.md) 2. [Data Deal](2-data-deal.md) -3. [Data Exchange Consent](3-data-exhange-consent.md) +3. [Data Provider Consent](3-data-provider-consent.md) 4. [Data Validation](4-data-validation.md) -5. [Incentives](5-incentives.md) -6. [Confidential Oracle](6-confidential-oracle.md) +5. [Confidential Oracle](5-confidential-oracle.md) +6. [Incentives](6-incentives.md) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/3-data-exhange-consent.md b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md similarity index 100% rename from .gitbook/3-protocol-devs/1-dep-specs/3-data-exhange-consent.md rename to .gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md diff --git a/.gitbook/3-protocol-devs/1-dep-specs/5-incentives.md b/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md similarity index 100% rename from .gitbook/3-protocol-devs/1-dep-specs/5-incentives.md rename to .gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md diff --git a/.gitbook/3-protocol-devs/1-dep-specs/6-confidential-oracle.md b/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md similarity index 100% rename from .gitbook/3-protocol-devs/1-dep-specs/6-confidential-oracle.md rename to .gitbook/3-protocol-devs/1-dep-specs/6-incentives.md diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index c7a8a0ca..bd6a902e 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -15,9 +15,9 @@ * CLI Keyring * GUI Wallets * Data Exchange - * Concepts - * Consume data - * Provide data + * [About DEP](1-users/3-data-exchange/0-about-dep.md) + * [Consume data](1-users/3-data-exchange/1-consume-data.md) + * [Provide data](1-users/3-data-exchange/2-provide-data.md) * Staking * Governance * Overview @@ -35,6 +35,13 @@ * [Overview](3-protocol-devs/0-overview.md) * Data Exchange Protocol Specs + * [Overview](3-protocol-devs/1-dep-specs/0-overview.md) + * [User Flow](3-protocol-devs/1-dep-specs/1-user-flow.md) + * [Data Deal](3-protocol-devs/1-dep-specs/2-data-deal.md) + * [Data Provider Consent](3-protocol-devs/1-dep-specs/3-data-provider-consent.md) + * [Data Validation](3-protocol-devs/1-dep-specs/4-data-validation.md) + * [Confidential Oracle](3-protocol-devs/1-dep-specs/5-confidential-oracle.md) + * [Incentives](3-protocol-devs/1-dep-specs/6-incentives.md) * Modules * Dev Guides From d0eae6fc1fa08b42faa21db792e17639a5bc0d88 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Thu, 22 Dec 2022 21:24:57 +0900 Subject: [PATCH 03/84] fix --- .gitbook/1-users/3-data-exchange/0-about-dep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md index 80549af7..8e7a2b49 100644 --- a/.gitbook/1-users/3-data-exchange/0-about-dep.md +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -4,7 +4,7 @@ Data Exchange Protocol (hereafter 'DEP') is a communication layer for sharing an between two parties in decentralized environments. -## tl;dr +## What DEP is Data consumers can open data deals by specifying what type of data and how much they want, and how much they can pay for it. From 2d0aa14cdd2f6dab2c2cb83ec541125aab87bf33 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Thu, 22 Dec 2022 22:50:48 +0900 Subject: [PATCH 04/84] fix --- .gitbook/5-oracles/{overview.md => 0-about-dep-oracle.md} | 0 .gitbook/README.md | 2 +- .gitbook/SUMMARY.md | 5 +---- 3 files changed, 2 insertions(+), 5 deletions(-) rename .gitbook/5-oracles/{overview.md => 0-about-dep-oracle.md} (100%) diff --git a/.gitbook/5-oracles/overview.md b/.gitbook/5-oracles/0-about-dep-oracle.md similarity index 100% rename from .gitbook/5-oracles/overview.md rename to .gitbook/5-oracles/0-about-dep-oracle.md diff --git a/.gitbook/README.md b/.gitbook/README.md index 83c9bec3..c1736438 100644 --- a/.gitbook/README.md +++ b/.gitbook/README.md @@ -5,4 +5,4 @@ - [For dApp Developers](2-dapp-devs/overview.md) - [For Protocol Developers](3-protocol-devs/0-overview.md) - [For Validators](4-validators/overview.md) -- [For Oracles](5-oracles/overview.md) +- [For Oracles](5-oracles/0-about-dep-oracle.md) diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index bd6a902e..346c2a30 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -61,9 +61,6 @@ ## For Oracles -* [Overview](5-oracles/overview.md) -* Data Exchange Protocol - * Concepts - * Oracle +* [About DEP Oracle](5-oracles/0-about-dep-oracle.md) * Operate Oracle Nodes * FAQ \ No newline at end of file From 915e8c95c6a775fec5ae34377fc43cf0480ccc13 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Thu, 22 Dec 2022 22:53:51 +0900 Subject: [PATCH 05/84] fix --- ...ea-ecosystem.md => 0-panacea-ecosystem.md} | 0 .../{roadmap.md => 1-roadmap.md} | 2 +- .../{overview.md => 0-overview.md} | 0 .../{overview.md => 0-overview.md} | 0 ...-installation.md => 1-cli-installation.md} | 0 ...eploy-localnet.md => 2-deploy-localnet.md} | 0 ...t-testnet.md => 3-join-mainnet-testnet.md} | 4 ++-- .../{cosmovisor.md => 4-cosmovisor.md} | 0 .../4-validators/5-security/0-sentry-nodes.md | 0 .../5-security/1-validator-backup.md | 0 .../2-ledger-nano.md} | 2 +- .../4-validators/6-software-upgrade-guide.md | 0 .gitbook/4-validators/{faq.md => 7-faq.md} | 2 +- .../interaction-with-the-network-cli.md | 2 +- .gitbook/README.md | 6 +++--- .gitbook/SUMMARY.md | 20 +++++++++---------- 16 files changed, 19 insertions(+), 19 deletions(-) rename .gitbook/0-about-panacea/{panacea-ecosystem.md => 0-panacea-ecosystem.md} (100%) rename .gitbook/0-about-panacea/{roadmap.md => 1-roadmap.md} (98%) rename .gitbook/2-dapp-devs/{overview.md => 0-overview.md} (100%) rename .gitbook/4-validators/{overview.md => 0-overview.md} (100%) rename .gitbook/4-validators/{cli-installation.md => 1-cli-installation.md} (100%) rename .gitbook/4-validators/{deploy-localnet.md => 2-deploy-localnet.md} (100%) rename .gitbook/4-validators/{join-mainnet-testnet.md => 3-join-mainnet-testnet.md} (98%) rename .gitbook/4-validators/{cosmovisor.md => 4-cosmovisor.md} (100%) create mode 100644 .gitbook/4-validators/5-security/0-sentry-nodes.md create mode 100644 .gitbook/4-validators/5-security/1-validator-backup.md rename .gitbook/4-validators/{ledger-nano.md => 5-security/2-ledger-nano.md} (97%) create mode 100644 .gitbook/4-validators/6-software-upgrade-guide.md rename .gitbook/4-validators/{faq.md => 7-faq.md} (99%) diff --git a/.gitbook/0-about-panacea/panacea-ecosystem.md b/.gitbook/0-about-panacea/0-panacea-ecosystem.md similarity index 100% rename from .gitbook/0-about-panacea/panacea-ecosystem.md rename to .gitbook/0-about-panacea/0-panacea-ecosystem.md diff --git a/.gitbook/0-about-panacea/roadmap.md b/.gitbook/0-about-panacea/1-roadmap.md similarity index 98% rename from .gitbook/0-about-panacea/roadmap.md rename to .gitbook/0-about-panacea/1-roadmap.md index 7a4436cd..b3bb8c42 100644 --- a/.gitbook/0-about-panacea/roadmap.md +++ b/.gitbook/0-about-panacea/1-roadmap.md @@ -14,7 +14,7 @@ This data exchange protocol is being developed to be as general as possible, so Well, it sounds like the protocol should work well, right? However, there are so many issues that we have to resolve. For privacy and security, data sellers should be able to expose only a small part of their data that is really desired by data buyers. Data transmission must be secure, so that anyone cannot steal data. In order to guarantee the right of data buyers, all criteria that data buyers specified has to be validated clearly before the payment is finalized. In addition, the ecosystem should be attractive enough for many data sellers and buyers to join. In order to resolve these challenges, the team is developing this data exchange protocol with several latest technologies. -The detailed tech stack of the data exchange protocol is described in the [Panacea Ecosystem](./panacea-ecosystem.md) document. +The detailed tech stack of the data exchange protocol is described in the [Panacea Ecosystem](./0-panacea-ecosystem.md) document. There will be more details that we have to solve, and we know that all of them cannot be achieved in one step. Hence, we will complete this big task step by step. In 2022, MediBloc will release the v0 of data exchange protocol as a proof of concept that includes only essential features. Also, a data marketplace web service will be introduced as a simple example service based on the protocol. Based on this proof of concepts, the data exchange protocol will be improved as v1 from 2023 with enhanced security and interoperability. MediBloc has already opened all source codes and progresses publicly on GitHub. We encourage anyone to join the project and share your insights. We are so excited and thrilled to share our vision to achieve our goal to become the world’s best patient centric health data platform. Thank you for your continued support! diff --git a/.gitbook/2-dapp-devs/overview.md b/.gitbook/2-dapp-devs/0-overview.md similarity index 100% rename from .gitbook/2-dapp-devs/overview.md rename to .gitbook/2-dapp-devs/0-overview.md diff --git a/.gitbook/4-validators/overview.md b/.gitbook/4-validators/0-overview.md similarity index 100% rename from .gitbook/4-validators/overview.md rename to .gitbook/4-validators/0-overview.md diff --git a/.gitbook/4-validators/cli-installation.md b/.gitbook/4-validators/1-cli-installation.md similarity index 100% rename from .gitbook/4-validators/cli-installation.md rename to .gitbook/4-validators/1-cli-installation.md diff --git a/.gitbook/4-validators/deploy-localnet.md b/.gitbook/4-validators/2-deploy-localnet.md similarity index 100% rename from .gitbook/4-validators/deploy-localnet.md rename to .gitbook/4-validators/2-deploy-localnet.md diff --git a/.gitbook/4-validators/join-mainnet-testnet.md b/.gitbook/4-validators/3-join-mainnet-testnet.md similarity index 98% rename from .gitbook/4-validators/join-mainnet-testnet.md rename to .gitbook/4-validators/3-join-mainnet-testnet.md index 31bdb1be..5837dce4 100644 --- a/.gitbook/4-validators/join-mainnet-testnet.md +++ b/.gitbook/4-validators/3-join-mainnet-testnet.md @@ -59,7 +59,7 @@ So, expose them to the network where you perform operational actions. ssh ubuntu@ -i .pem ``` -Install prerequisites by following the [Installation](cli-installation.md) guide. +Install prerequisites by following the [Installation](1-cli-installation.md) guide. ## Setup a New Node @@ -206,7 +206,7 @@ Environment="DAEMON_NAME=panacead" Environment="DAEMON_ALLOW_DOWNLOAD_BINARIES=false" Environment="DAEMON_RESTART_AFTER_UPGRADE=true" ``` -For more details about those environment variables, please see the [Cosmovisor guide](cosmovisor.md). +For more details about those environment variables, please see the [Cosmovisor guide](4-cosmovisor.md). Then, setup the daemon. ```bash diff --git a/.gitbook/4-validators/cosmovisor.md b/.gitbook/4-validators/4-cosmovisor.md similarity index 100% rename from .gitbook/4-validators/cosmovisor.md rename to .gitbook/4-validators/4-cosmovisor.md diff --git a/.gitbook/4-validators/5-security/0-sentry-nodes.md b/.gitbook/4-validators/5-security/0-sentry-nodes.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/4-validators/5-security/1-validator-backup.md b/.gitbook/4-validators/5-security/1-validator-backup.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/4-validators/ledger-nano.md b/.gitbook/4-validators/5-security/2-ledger-nano.md similarity index 97% rename from .gitbook/4-validators/ledger-nano.md rename to .gitbook/4-validators/5-security/2-ledger-nano.md index 176de319..acacae5a 100644 --- a/.gitbook/4-validators/ledger-nano.md +++ b/.gitbook/4-validators/5-security/2-ledger-nano.md @@ -23,7 +23,7 @@ Note: You need to [install the `Panacea` app](#install-the-panacea-ledger-app) o ### Before you begin -Install `panacead` by following the [guide](cli-installation.md). +Install `panacead` by following the [guide](../1-cli-installation.md). ### Add your Ledger key diff --git a/.gitbook/4-validators/6-software-upgrade-guide.md b/.gitbook/4-validators/6-software-upgrade-guide.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/4-validators/faq.md b/.gitbook/4-validators/7-faq.md similarity index 99% rename from .gitbook/4-validators/faq.md rename to .gitbook/4-validators/7-faq.md index 0c0bb6cc..266df02f 100644 --- a/.gitbook/4-validators/faq.md +++ b/.gitbook/4-validators/7-faq.md @@ -258,7 +258,7 @@ There are currently two faults that can result in slashing of funds for a valida Validators should expect to provision one or more data center locations with redundant power, networking, firewalls, HSMs and servers. We expect that a modest level of hardware specifications will be needed initially and that they might rise as network use increases. -For details, please see the [Join the Network](join-mainnet-testnet.md) guide. +For details, please see the [Join the Network](3-join-mainnet-testnet.md) guide. ### What are software requirements? diff --git a/.gitbook/4-validators/interaction-with-the-network-cli.md b/.gitbook/4-validators/interaction-with-the-network-cli.md index 98353436..bfec395e 100644 --- a/.gitbook/4-validators/interaction-with-the-network-cli.md +++ b/.gitbook/4-validators/interaction-with-the-network-cli.md @@ -257,7 +257,7 @@ panacead query slashing params ### Create your validator {% hint style="info" %} -This guide assumes that you have already set up your full node by following [the guide](join-mainnet-testnet.md). +This guide assumes that you have already set up your full node by following [the guide](3-join-mainnet-testnet.md). {% endhint %} Your `panaceavalconspub` address (public key) can be used to create a new validator by staking tokens. diff --git a/.gitbook/README.md b/.gitbook/README.md index c1736438..d961e87e 100644 --- a/.gitbook/README.md +++ b/.gitbook/README.md @@ -1,8 +1,8 @@ # MediBloc Panacea Documentation -- [About Panacea](0-about-panacea/panacea-ecosystem.md) +- [About Panacea](0-about-panacea/0-panacea-ecosystem.md) - [For Users](1-users/0-overview.md) -- [For dApp Developers](2-dapp-devs/overview.md) +- [For dApp Developers](2-dapp-devs/0-overview.md) - [For Protocol Developers](3-protocol-devs/0-overview.md) -- [For Validators](4-validators/overview.md) +- [For Validators](4-validators/0-overview.md) - [For Oracles](5-oracles/0-about-dep-oracle.md) diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index 346c2a30..6311f10a 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -2,8 +2,8 @@ ## Overview -* [Panacea Ecosystem](0-about-panacea/panacea-ecosystem.md) -* [Roadmap](0-about-panacea/roadmap.md) +* [Panacea Ecosystem](0-about-panacea/0-panacea-ecosystem.md) +* [Roadmap](0-about-panacea/1-roadmap.md) ## For Users @@ -27,7 +27,7 @@ ## For dApp Devs -* [Overview](2-dapp-devs/overview.md) +* [Overview](2-dapp-devs/0-overview.md) * Endpoints * Client Libraries @@ -47,17 +47,17 @@ ## For Validators -* [Overview](4-validators/overview.md) -* [CLI Installation](4-validators/cli-installation.md) -* [Deploy Localnet](4-validators/deploy-localnet.md) -* [Join Mainnet/Testnet](4-validators/join-mainnet-testnet.md) -* [Cosmovisor](4-validators/cosmovisor.md) +* [Overview](4-validators/0-overview.md) +* [CLI Installation](4-validators/1-cli-installation.md) +* [Deploy Localnet](4-validators/2-deploy-localnet.md) +* [Join Mainnet/Testnet](4-validators/3-join-mainnet-testnet.md) +* [Cosmovisor](4-validators/4-cosmovisor.md) * Security * Sentry Nodes * Validator Backup - * [Ledger Nano](4-validators/ledger-nano.md) + * [Ledger Nano](4-validators/5-security/2-ledger-nano.md) * Software Upgrade Guide -* [FAQ](4-validators/faq.md) +* [FAQ](4-validators/7-faq.md) ## For Oracles From 963f489cba58ec68caad42fe0386a8de02588bae Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Thu, 22 Dec 2022 23:13:39 +0900 Subject: [PATCH 06/84] fix --- .gitbook/1-users/3-data-exchange/0-about-dep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md index 8e7a2b49..6e3916c5 100644 --- a/.gitbook/1-users/3-data-exchange/0-about-dep.md +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -4,7 +4,7 @@ Data Exchange Protocol (hereafter 'DEP') is a communication layer for sharing an between two parties in decentralized environments. -## What DEP is +## What is DEP? Data consumers can open data deals by specifying what type of data and how much they want, and how much they can pay for it. From d0cae2320d860f7f6cb76ff4a63ffe5df56a9eeb Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 23 Dec 2022 12:09:31 +0900 Subject: [PATCH 07/84] consume data --- .../1-users/3-data-exchange/1-consume-data.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index e69de29b..a3dfbe63 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -0,0 +1,88 @@ +# Consume data + +Data consumers can open data deals by specifying what type of data and how much they want, and how much they can pay for it. + +Data deals are registered in the Panacea public blockchain, so all data providers can find data deals which match their data. + + +## Create a data deal + +Broadcast the following `create-deal` transaction with specifying data schema, a data count, and a budget. +```bash +panacead tx datadeal create-deal ${deal-file-path} \ + --from ${data-consumer-addr} \ + --chain-id ${chain-id} \ + --gas auto --gas-adjustment 1.30 --gas-prices 5umed \ + --node ${chain-node-rpc-addr} +``` + +For `[deal-file-path]`, create a following JSON file. +```json +{ + +} +``` +It is very important to set data schema specifically, so that data being provided can be validated accurately by oracles. + +For more details about data deals, please see the [Data Deal](../../3-protocol-devs/1-dep-specs/2-data-deal.md) specification. + + +## Query deals + +You can query a deal with its deal ID. +```bash +panacead query datadeal deal ${deal-id} \ + --node ${chain-node-rpc-addr} +``` +Also, you can query all deals registered in the chain. +```bash +panacead query datadeal deals \ + --node ${chain-node-rpc-addr} +``` + + +## Query consents + +If some data consumers have data which fits requirements of your data deal, they will submit consents to the chain. +The consent means that the data provider agreed to provide their data to the specific data consumer. +Also, each consent can contain a data validation certificate issued by an oracle, so that data consumers can trust the validity of data. + +As soon as data providers submit their consents, you can query all consents submitted to a specific data deal. +```bash +panacead query datadeal consents ${deal-id} \ + --node ${chain-node-rpc-addr} +``` +Or, you can query a specific consent which contains a certain data hash. +```bash +panacead query datadeal consent ${deal-id} ${data-hash} \ + --node ${chain-node-rpc-addr} +``` + +For more details about data consents, please see the [Data Provider Consent](../../3-protocol-devs/1-dep-specs/3-data-provider-consent.md) specification. + + +## Access data + +A data validation certificate issued by an oracle contains how the data can be accessed. +For example, if the oracle decides to transmit data via IPFS, the certificate will contain a CID of data. +If so, you can access any IPFS node which is connected to the public IPFS network, and can obtain the data. + +For more details about data validation certificates, please see the [Data Validation](../../3-protocol-devs/1-dep-specs/4-data-validation.md) specification. + +In general, the data transmitted is encrypted by oracles, so that only the specific data consumer is able to decrypt it. +Using the following REST API, you can get a secret key of each data from the oracle which issued the data validation certificate. +```bash +curl -v -X GET -H "Authorization: Bearer ${jwt}" \ + "${oracle-url}/v0/data-deal/secret-key?deal-id=${deal-id}&data-hash=${data-hash}" +``` +You must specify a JWT issued by yourself in order to prove that you are the data consumer who created the data deal. +Please note that the returned secret key is also encrypted, so that also the specific data consumer decrypt the key using his/her Panacea account private key. +Nevertheless, we highly recommend you to communicate with oracles who provides an HTTPS endpoint with SSL/TLS encryption. + +Using the encrypted secret key that you obtained from the oracle, you can decrypt data by the following CLI. +```bash +panacead decrypt-data ${input-file-path} ${your-account-key-name} ${encrypted-secret-key} \ + --node ${chain-node-rpc-addr} +``` +This command will decrypt the secret key using your account key first, and decrypt the data using the secret key. +So, please note that you should specify the `your-account-key-name` which is registered in the `panacead` keyring. From ef00c1e92fa6063750cb085d2afa4fbc26d7bd7e Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 23 Dec 2022 13:02:27 +0900 Subject: [PATCH 08/84] spec --- .../1-users/3-data-exchange/2-provide-data.md | 1 + .../1-dep-specs/1-user-flow.md | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/.gitbook/1-users/3-data-exchange/2-provide-data.md b/.gitbook/1-users/3-data-exchange/2-provide-data.md index e69de29b..e827d666 100644 --- a/.gitbook/1-users/3-data-exchange/2-provide-data.md +++ b/.gitbook/1-users/3-data-exchange/2-provide-data.md @@ -0,0 +1 @@ +# Consume data diff --git a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md index e69de29b..e6bad67a 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md @@ -0,0 +1,57 @@ +# User Flow + +- Status: Draft +- Created: 2022-12-23 +- Modified: 2022-12-23 +- Authors + - Youngjoon Lee + - Gyuguen Jang + - Hansol Lee + - Myongsik Gong + - Inchul Song + + +## Synopsis + +TODO: Blah blah... + +### Motivation + +TODO: Blah blah... + +### Definitions + +- `Data Provider`: TODO +- TODO + + +## Technical Specification + +### User Flow + +TODO: blahblah with diagrams (e.g. seq diagrams) + + +## Backwards Compatibility + +Not applicable. + +## Forwards Compatibility + +TODO: blahblah + +## Example Implementations + +TODO: Repo URLs of panacea-core and panacea-oracle with specific tags + +## Other Implementations + +None at present. + +## History + +- 2022-12-23: Initial draft finished + +## Copyright + +All content herin is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file From f6faecc0149ddce7937817062440b4e7aa780f16 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 23 Dec 2022 13:09:58 +0900 Subject: [PATCH 09/84] typo --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 7 ++++++- .gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index a3dfbe63..c583ae8a 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -76,7 +76,12 @@ curl -v -X GET -H "Authorization: Bearer ${jwt}" \ "${oracle-url}/v0/data-deal/secret-key?deal-id=${deal-id}&data-hash=${data-hash}" ``` You must specify a JWT issued by yourself in order to prove that you are the data consumer who created the data deal. -Please note that the returned secret key is also encrypted, so that also the specific data consumer decrypt the key using his/her Panacea account private key. +For that authentication, the JWT must be signed by your (data consumer's) chain account private key. + +We highly recommend to set the expiration of JWT as short as possible for security reasons. +In near future, the protocol will adopt the 'nonce' concept to improve the security of authentications. + +Please note that the returned secret key is also encrypted, so that also the specific data consumer decrypt the key using his/her chain account private key. Nevertheless, we highly recommend you to communicate with oracles who provides an HTTPS endpoint with SSL/TLS encryption. Using the encrypted secret key that you obtained from the oracle, you can decrypt data by the following CLI. diff --git a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md index e6bad67a..60171b94 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md @@ -54,4 +54,4 @@ None at present. ## Copyright -All content herin is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file From e43756cf8203f199b3b3b4845ee68bd5ab774319 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 23 Dec 2022 13:13:07 +0900 Subject: [PATCH 10/84] link --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index c583ae8a..1ebd4d5b 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -64,7 +64,7 @@ For more details about data consents, please see the [Data Provider Consent](../ ## Access data A data validation certificate issued by an oracle contains how the data can be accessed. -For example, if the oracle decides to transmit data via IPFS, the certificate will contain a CID of data. +For example, if the oracle decides to transmit data via [IPFS](https://ipfs.tech/), the certificate will contain a [CID](https://docs.ipfs.io/concepts/content-addressing/) of data. If so, you can access any IPFS node which is connected to the public IPFS network, and can obtain the data. For more details about data validation certificates, please see the [Data Validation](../../3-protocol-devs/1-dep-specs/4-data-validation.md) specification. From 6b226b82afedd1d470937235eee9e9eb507ccc97 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 23 Dec 2022 13:35:41 +0900 Subject: [PATCH 11/84] tmp --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 1ebd4d5b..c87f6c9b 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -16,7 +16,7 @@ panacead tx datadeal create-deal ${deal-file-path} \ --node ${chain-node-rpc-addr} ``` -For `[deal-file-path]`, create a following JSON file. +For `deal-file-path`, create a following JSON file. ```json { From 627435791df67c5466185870fc59596fa5b0c882 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:23:22 +0900 Subject: [PATCH 12/84] Update .gitbook/0-about-panacea/1-roadmap.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/0-about-panacea/1-roadmap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/0-about-panacea/1-roadmap.md b/.gitbook/0-about-panacea/1-roadmap.md index b3bb8c42..37be3c67 100644 --- a/.gitbook/0-about-panacea/1-roadmap.md +++ b/.gitbook/0-about-panacea/1-roadmap.md @@ -11,7 +11,7 @@ Nowadays, many businesses and technologies are data-driven. Many companies are a Our data exchange protocol has the concept of data Pool, so that anyone can specify the type and the quantity of the data they want. Also, they can specify how much cryptocurrency they are willing to pay for the data. All of these data pools are recorded in Panacea and everyone who wants to sell their data can see all data pools. Data sellers can choose data pools by checking how many parts of their data to be shared to data buyers. Then, they sign the consents for data exchange. Verified off-chain data validators validate whether data provided by data sellers conforms to criteria that data pool creator has specified. If all the requirements are met, the data is provided to data buyers via secure connections and the promised amount of cryptocurrency is transferred to data sellers. In this entire protocol, data is not recorded on any blockchain such as Panacea. All data transmissions are performed off-chain and Panacea guarantees all agreements for data exchanges and transparent payments. This data exchange protocol is being developed to be as general as possible, so that not only the healthcare data but also all the other types of data can be handled by the protocol. Since Panacea and data exchange protocol is publicly opened, any service providers can build their own services on the top of the data exchange protocol, so that their users can exchange their data securely and get proper rewards. As the first use case, MediBloc is going to build a healthcare data marketplace service based on this protocol. -Well, it sounds like the protocol should work well, right? However, there are so many issues that we have to resolve. For privacy and security, data sellers should be able to expose only a small part of their data that is really desired by data buyers. Data transmission must be secure, so that anyone cannot steal data. In order to guarantee the right of data buyers, all criteria that data buyers specified has to be validated clearly before the payment is finalized. In addition, the ecosystem should be attractive enough for many data sellers and buyers to join. +Well, it sounds like the protocol should work well, right? However, there are many issues that we have to resolve. For privacy and security, data sellers should be able to expose only a small part of their data that is really desired by data buyers. Also, data transmission must be secure, so that no one can steal or intercept the data. In order to guarantee the right of data buyers, all criteria that data buyers specified has to be validated clearly before the payment is finalized. Last but not least, the ecosystem should be attractive enough for many data sellers and buyers to join. In order to resolve these challenges, the team is developing this data exchange protocol with several latest technologies. The detailed tech stack of the data exchange protocol is described in the [Panacea Ecosystem](./0-panacea-ecosystem.md) document. From 37085a481278a3e3d3fb01b7e30ec0775a3d17a1 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:24:22 +0900 Subject: [PATCH 13/84] Update .gitbook/0-about-panacea/1-roadmap.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/0-about-panacea/1-roadmap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/0-about-panacea/1-roadmap.md b/.gitbook/0-about-panacea/1-roadmap.md index 37be3c67..9f964c87 100644 --- a/.gitbook/0-about-panacea/1-roadmap.md +++ b/.gitbook/0-about-panacea/1-roadmap.md @@ -16,5 +16,5 @@ Well, it sounds like the protocol should work well, right? However, there are ma In order to resolve these challenges, the team is developing this data exchange protocol with several latest technologies. The detailed tech stack of the data exchange protocol is described in the [Panacea Ecosystem](./0-panacea-ecosystem.md) document. -There will be more details that we have to solve, and we know that all of them cannot be achieved in one step. Hence, we will complete this big task step by step. In 2022, MediBloc will release the v0 of data exchange protocol as a proof of concept that includes only essential features. Also, a data marketplace web service will be introduced as a simple example service based on the protocol. Based on this proof of concepts, the data exchange protocol will be improved as v1 from 2023 with enhanced security and interoperability. MediBloc has already opened all source codes and progresses publicly on GitHub. We encourage anyone to join the project and share your insights. +There will be more detailed issues that we would have to solve, and we know that all of them cannot be solved in one step. Hence, we will complete this big task step by step. In 2022, MediBloc have released the v0 of data exchange protocol as a proof of concept that includes only essential features on testnet. Based on this proof of concepts, the data exchange protocol will be improved as v1 in 2023 with enhanced security and interoperability. Also, MediBloc will be introducing dApps for data providers using data exchange protocol and keep designing the services that go on top of data exchange protocol. MediBloc has already opened all source codes and progresses publicly on GitHub. We encourage anyone to join the project and share your insights. We are so excited and thrilled to share our vision to achieve our goal to become the world’s best patient centric health data platform. Thank you for your continued support! From 427af07c11abd524b485b40c20a6c51799b167f6 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:24:59 +0900 Subject: [PATCH 14/84] Update .gitbook/1-users/3-data-exchange/0-about-dep.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/0-about-dep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md index 6e3916c5..09911bd6 100644 --- a/.gitbook/1-users/3-data-exchange/0-about-dep.md +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -6,7 +6,7 @@ between two parties in decentralized environments. ## What is DEP? -Data consumers can open data deals by specifying what type of data and how much they want, and how much they can pay for it. +Data consumers can open data deals by specifying the type, the quantity, and the pricing of the data that they are willing to consume. Data providers can choose deals that match the data they have and they are willing to provide. From 0fa399faf420855070f855dd657b50991b79455d Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:25:09 +0900 Subject: [PATCH 15/84] Update .gitbook/1-users/3-data-exchange/0-about-dep.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/0-about-dep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md index 09911bd6..c211867b 100644 --- a/.gitbook/1-users/3-data-exchange/0-about-dep.md +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -4,7 +4,7 @@ Data Exchange Protocol (hereafter 'DEP') is a communication layer for sharing an between two parties in decentralized environments. -## What is DEP? +## What can you do with DEP? Data consumers can open data deals by specifying the type, the quantity, and the pricing of the data that they are willing to consume. From 4423709bd75b7c694dca53a70e549ed555d8044c Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:25:36 +0900 Subject: [PATCH 16/84] Update .gitbook/1-users/3-data-exchange/0-about-dep.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/0-about-dep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md index c211867b..9543aa64 100644 --- a/.gitbook/1-users/3-data-exchange/0-about-dep.md +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -8,7 +8,7 @@ between two parties in decentralized environments. Data consumers can open data deals by specifying the type, the quantity, and the pricing of the data that they are willing to consume. -Data providers can choose deals that match the data they have and they are willing to provide. +Data providers can choose and participate in the deals that match the data that they have when they are willing to provide. To guarantee data consumers can only consume data in the form they want, decentralized oracles verify and issue certificates for all data being shared From 701637eee4172087079c15012268b264ddd9338d Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:26:06 +0900 Subject: [PATCH 17/84] Update .gitbook/1-users/3-data-exchange/0-about-dep.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/0-about-dep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md index 9543aa64..5a878b24 100644 --- a/.gitbook/1-users/3-data-exchange/0-about-dep.md +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -10,7 +10,7 @@ Data consumers can open data deals by specifying the type, the quantity, and the Data providers can choose and participate in the deals that match the data that they have when they are willing to provide. -To guarantee data consumers can only consume data in the form they want, +To guarantee data consumers only consume data in the form they want, decentralized oracles verify and issue certificates for all data being shared Panacea public blockchain manages the status of all data deals and data sharing consents, From d18fdb6c64642f7e8c699cc7ef2d265d0eb47139 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:26:23 +0900 Subject: [PATCH 18/84] Update .gitbook/1-users/3-data-exchange/0-about-dep.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/0-about-dep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md index 5a878b24..d696e862 100644 --- a/.gitbook/1-users/3-data-exchange/0-about-dep.md +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -11,7 +11,7 @@ Data consumers can open data deals by specifying the type, the quantity, and the Data providers can choose and participate in the deals that match the data that they have when they are willing to provide. To guarantee data consumers only consume data in the form they want, -decentralized oracles verify and issue certificates for all data being shared +decentralized oracles verify and issue certificates for all data being provided by the data provider. Panacea public blockchain manages the status of all data deals and data sharing consents, ensuring data providers and ecosystem operators are rewarded appropriately. From 71708edc35780e125934ab7a7fdc3609e703130f Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:26:30 +0900 Subject: [PATCH 19/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index c87f6c9b..174df9f9 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -69,7 +69,7 @@ If so, you can access any IPFS node which is connected to the public IPFS networ For more details about data validation certificates, please see the [Data Validation](../../3-protocol-devs/1-dep-specs/4-data-validation.md) specification. -In general, the data transmitted is encrypted by oracles, so that only the specific data consumer is able to decrypt it. +In general, the data transmitted is encrypted by oracles, so that only a specific data consumer is able to decrypt it. Using the following REST API, you can get a secret key of each data from the oracle which issued the data validation certificate. ```bash curl -v -X GET -H "Authorization: Bearer ${jwt}" \ From 7d54cafeb384cc7acc9be7ec4b4be1965039b53f Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:26:37 +0900 Subject: [PATCH 20/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 174df9f9..330d6bb7 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -70,7 +70,7 @@ If so, you can access any IPFS node which is connected to the public IPFS networ For more details about data validation certificates, please see the [Data Validation](../../3-protocol-devs/1-dep-specs/4-data-validation.md) specification. In general, the data transmitted is encrypted by oracles, so that only a specific data consumer is able to decrypt it. -Using the following REST API, you can get a secret key of each data from the oracle which issued the data validation certificate. +Using the following REST API, you can get a secret key of each data from the oracle that issued the data validation certificate. ```bash curl -v -X GET -H "Authorization: Bearer ${jwt}" \ "${oracle-url}/v0/data-deal/secret-key?deal-id=${deal-id}&data-hash=${data-hash}" From 9f4a242ebb77ae677b78e0b07b714469f86f4974 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:26:44 +0900 Subject: [PATCH 21/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 330d6bb7..bea615f0 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -76,7 +76,7 @@ curl -v -X GET -H "Authorization: Bearer ${jwt}" \ "${oracle-url}/v0/data-deal/secret-key?deal-id=${deal-id}&data-hash=${data-hash}" ``` You must specify a JWT issued by yourself in order to prove that you are the data consumer who created the data deal. -For that authentication, the JWT must be signed by your (data consumer's) chain account private key. +For this authentication, the JWT must be signed by your (data consumer's) chain account private key. We highly recommend to set the expiration of JWT as short as possible for security reasons. In near future, the protocol will adopt the 'nonce' concept to improve the security of authentications. From fa7116b86d62ca5cf29045fb5b87e85004a448ad Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:26:56 +0900 Subject: [PATCH 22/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index bea615f0..07585d19 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -81,7 +81,7 @@ For this authentication, the JWT must be signed by your (data consumer's) chain We highly recommend to set the expiration of JWT as short as possible for security reasons. In near future, the protocol will adopt the 'nonce' concept to improve the security of authentications. -Please note that the returned secret key is also encrypted, so that also the specific data consumer decrypt the key using his/her chain account private key. +Please note that the returned secret key is also encrypted, so that only the specific data consumers can decrypt the key using his/her chain account private key. Nevertheless, we highly recommend you to communicate with oracles who provides an HTTPS endpoint with SSL/TLS encryption. Using the encrypted secret key that you obtained from the oracle, you can decrypt data by the following CLI. From fa9d0ce9d2197081182108482a43e366bcff7560 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:27:12 +0900 Subject: [PATCH 23/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 07585d19..28bbaa23 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -89,5 +89,5 @@ Using the encrypted secret key that you obtained from the oracle, you can decryp panacead decrypt-data ${input-file-path} ${your-account-key-name} ${encrypted-secret-key} \ --node ${chain-node-rpc-addr} ``` -This command will decrypt the secret key using your account key first, and decrypt the data using the secret key. +This command will decrypt the secret key using your account key first, and decrypt the data using the decrypted secret key. So, please note that you should specify the `your-account-key-name` which is registered in the `panacead` keyring. From 7205c04b0f89c6482af1fe8eb855d9faf541d09c Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:27:28 +0900 Subject: [PATCH 24/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 28bbaa23..e1c26c50 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -1,6 +1,6 @@ # Consume data -Data consumers can open data deals by specifying what type of data and how much they want, and how much they can pay for it. +Data consumers can open data deals by specifying the type, the quantity, and the pricing of the data that they are willing to consume. Data deals are registered in the Panacea public blockchain, so all data providers can find data deals which match their data. From 38d124ab26736aed47ecab5a6a5b42f7101fefd5 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:27:43 +0900 Subject: [PATCH 25/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index e1c26c50..a1c98ba0 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -7,7 +7,7 @@ Data deals are registered in the Panacea public blockchain, so all data provider ## Create a data deal -Broadcast the following `create-deal` transaction with specifying data schema, a data count, and a budget. +Broadcast the following `create-deal` transaction with specifying data schema, a data count, and a budget in the deal-file in JSON format. ```bash panacead tx datadeal create-deal ${deal-file-path} \ --from ${data-consumer-addr} \ From 92ce731b5298d7171b4355411cf4f44e2748a129 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:28:03 +0900 Subject: [PATCH 26/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index a1c98ba0..28459e93 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -22,7 +22,7 @@ For `deal-file-path`, create a following JSON file. } ``` -It is very important to set data schema specifically, so that data being provided can be validated accurately by oracles. +It is very important to set data schema specifically and correctly, so that data being provided can be validated accurately by oracles. For more details about data deals, please see the [Data Deal](../../3-protocol-devs/1-dep-specs/2-data-deal.md) specification. From 13c9776a5caa97cb3dc97b743c299bb1d6d72adb Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:28:14 +0900 Subject: [PATCH 27/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 28459e93..06c3bea2 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -2,7 +2,7 @@ Data consumers can open data deals by specifying the type, the quantity, and the pricing of the data that they are willing to consume. -Data deals are registered in the Panacea public blockchain, so all data providers can find data deals which match their data. +Data deals are registered in the Panacea public blockchain, so all data providers can find data deals, which match their data. ## Create a data deal From 7d9b4df5877af779b7a003cf117356e3a637803d Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:28:26 +0900 Subject: [PATCH 28/84] Update .gitbook/3-protocol-devs/1-dep-specs/0-overview.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/3-protocol-devs/1-dep-specs/0-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md b/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md index 0e23c72f..2ddab77b 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/0-overview.md @@ -1,7 +1,7 @@ # Data Exchange Protocol Specifications Prior to diving into the technical specifications of Data Exchange Protocol (hereafter 'DEP'), -we recommend you to understand what DEP is, its motivation, and goals from the [About DEP](../../1-users/3-data-exchange/0-about-dep.md) documentation. +we recommend you to understand the definition of DEP, its motivation, and its goals from the [About DEP](../../1-users/3-data-exchange/0-about-dep.md) documentation. ## Specifications From 9174493284f6fc7bd4eaf21515f2244421cee3cf Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:28:37 +0900 Subject: [PATCH 29/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 06c3bea2..8ae7c9a1 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -43,7 +43,7 @@ panacead query datadeal deals \ ## Query consents -If some data consumers have data which fits requirements of your data deal, they will submit consents to the chain. +If some data consumers have data that fit the requirements of your data deal, they will submit consents to the chain. The consent means that the data provider agreed to provide their data to the specific data consumer. Also, each consent can contain a data validation certificate issued by an oracle, so that data consumers can trust the validity of data. From fc5e8093ef4138db01fd2f8c478e0ccfde47fe63 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:28:57 +0900 Subject: [PATCH 30/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 8ae7c9a1..8071cddf 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -44,7 +44,7 @@ panacead query datadeal deals \ ## Query consents If some data consumers have data that fit the requirements of your data deal, they will submit consents to the chain. -The consent means that the data provider agreed to provide their data to the specific data consumer. +The consent means that the data provider has agreed to provide their data to a specific data consumer. Also, each consent can contain a data validation certificate issued by an oracle, so that data consumers can trust the validity of data. As soon as data providers submit their consents, you can query all consents submitted to a specific data deal. From 28f6c5677b9dd6bfbd6cbd783584b56e892cb45f Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:29:07 +0900 Subject: [PATCH 31/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 8071cddf..2febc391 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -52,7 +52,7 @@ As soon as data providers submit their consents, you can query all consents subm panacead query datadeal consents ${deal-id} \ --node ${chain-node-rpc-addr} ``` -Or, you can query a specific consent which contains a certain data hash. +Or, you can query a specific consent, which contains a certain data hash. ```bash panacead query datadeal consent ${deal-id} ${data-hash} \ --node ${chain-node-rpc-addr} From 34bb9cf134bb223cb762144cc44ff024aa45d250 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:29:28 +0900 Subject: [PATCH 32/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 2febc391..378e2f40 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -63,7 +63,7 @@ For more details about data consents, please see the [Data Provider Consent](../ ## Access data -A data validation certificate issued by an oracle contains how the data can be accessed. +A data validation certificate issued by an oracle contains the methods to access the data. For example, if the oracle decides to transmit data via [IPFS](https://ipfs.tech/), the certificate will contain a [CID](https://docs.ipfs.io/concepts/content-addressing/) of data. If so, you can access any IPFS node which is connected to the public IPFS network, and can obtain the data. From 8cb59758a7e1dbeffa9b01052702bc37e12e3a9e Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Wed, 4 Jan 2023 16:29:46 +0900 Subject: [PATCH 33/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 378e2f40..c5c5b331 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -65,7 +65,7 @@ For more details about data consents, please see the [Data Provider Consent](../ A data validation certificate issued by an oracle contains the methods to access the data. For example, if the oracle decides to transmit data via [IPFS](https://ipfs.tech/), the certificate will contain a [CID](https://docs.ipfs.io/concepts/content-addressing/) of data. -If so, you can access any IPFS node which is connected to the public IPFS network, and can obtain the data. +If so, you can access any IPFS node connected to the public IPFS network, and obtain the data. For more details about data validation certificates, please see the [Data Validation](../../3-protocol-devs/1-dep-specs/4-data-validation.md) specification. From 164304651bc5da62a9c6e510474cfd6c7ef4e9ab Mon Sep 17 00:00:00 2001 From: Hansol Lee <38912532+H4NLee@users.noreply.github.com> Date: Thu, 5 Jan 2023 13:45:25 +0900 Subject: [PATCH 34/84] docs: add data-deal specs for protocol devs (#585) --- .../1-dep-specs/2-data-deal.md | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md index e69de29b..a0047cef 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md @@ -0,0 +1,121 @@ +# Data Deal + +- Status: Draft +- Created: 2023-01-03 +- Modified: 2023-01-03 +- Authors + - Youngjoon Lee + - Gyuguen Jang + - Hansol Lee + - Myongsik Gong + - Inchul Song + + +## Synopsis + +This document defines a data deal which is a contract for data collecting and pay for provision in [DEP](../../1-users/3-data-exchange/0-about-dep.md). +Data consumers create data deals by specifying the type, the quantity, and the pricing of the data that they are willing to consume. +Data providers can provide their data to the deals that match the type of data they have. +When a data provider provides data to the deal, the payout is distributed to the provider and the oracle that validated the data. +Also, data consumers can deactivate their data deal whenever they want and the remained budget would be refunded to the consumer's account. + +### Motivation + +Data consumers want different types of data, and even for the same type of data, they all differ in how much they want and how much they are willing to pay. +Thus, the data deal was devised so that data consumers can determine the type of data they want, as much as they want, at a cost they want. + +### Definitions + +`Data Provider`, `Data Consumer` and `Oracle` are defined in [User Flow](./1-user-flow.md) + +## Technical Specification + +Data consumers should be able to post the information described below publicly, so that any data provider can see it. +Also, data providers should be able to be assured that a particular data consumer really posted the information. +To meet these requirements, it is recommended to use a public decentralized state machine as a single point of truth, such as Panacea. + +### Data Structure of Deal + +The structure of data deal. + +```proto +message Deal { + uint64 id = 1; + string address = 2; + repeated string data_schema = 3; + cosmos.base.v1beta1.Coin budget = 4; + uint64 max_num_data = 5; + uint64 cur_num_data = 6; + string consumer_address = 7; + DealStatus status = 8; +} +``` + +- `id`: Auto increment id +- `address`: An address of deal generated when deal is created +- `data_schema`: A list of URLs of desired data schema +- `budget`: A budget for consuming data +- `max_num_data`: The maximum number of data the consumer want +- `cur_num_data`: The current number of data provided +- `consumer_address`: A consumer's account address of the form `panacea1...` +- `status`: The status of deal. 3 statuses can be possible + - `DEAL_STATUS_ACTIVE`: The status when deal is active (`cur_num_data` < `max_num_data`). + - `DEAL_STATUS_INACTIVE`: The status when deal is deactivated (when consumer deactivated the deal) + - `DEAL_STATUS_COMPLETED`: The status when deal is completed (`max_num_data` of data is provided) + +### Create Data Deal + +Data consumers can create their deal with the followings: + +```proto +message MsgCreateDeal { + repeated string data_schema = 1; + cosmos.base.v1beta1.Coin budget = 2; + uint64 max_num_data = 3; + string consumer_address = 4; +} +``` + +When deal is created, the amount of budget is sent from consumer's account to deal's account. +In other words, the balance of consumer's account should be greater or equal than the budget. + +### Deactivate Data Deal + +The consumer who created the deal can deactivate the deal at any time as long as `max_num_data` of data is not provided. + +To deactivate deal, the id of deal should be specified. + +```proto +message MsgDeactivateDeal { + uint64 deal_id = 1; + string requester_address = 2; +} +``` + +When deal is deactivated, all the remained budget is refunded to the consumer's account. +After deal is deactivated, no providers can provide their data to this deal, and the status of the deal would be `DEAL_STATUS_INACTIVE`. + +## Backwards Compatibility + +Not applicable. + +## Forwards Compatibility + +For now, JSON schema validation is used for data validation. +It can be expanded using JSON-LD contexts for verifiable credentials in the future. + +## Example Implementations + +Coming soon. + +## Other Implementations + +None at present. + +## History + +- 2023-01-03: Initial draft finished + +## Copyright + +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file From 950574f4b0e79aff653a95a19852204572564d8c Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 6 Jan 2023 10:11:42 +0900 Subject: [PATCH 35/84] Update .gitbook/0-about-panacea/1-roadmap.md Co-authored-by: Hansol Lee <38912532+H4NLee@users.noreply.github.com> --- .gitbook/0-about-panacea/1-roadmap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/0-about-panacea/1-roadmap.md b/.gitbook/0-about-panacea/1-roadmap.md index 9f964c87..cad895e6 100644 --- a/.gitbook/0-about-panacea/1-roadmap.md +++ b/.gitbook/0-about-panacea/1-roadmap.md @@ -11,7 +11,7 @@ Nowadays, many businesses and technologies are data-driven. Many companies are a Our data exchange protocol has the concept of data Pool, so that anyone can specify the type and the quantity of the data they want. Also, they can specify how much cryptocurrency they are willing to pay for the data. All of these data pools are recorded in Panacea and everyone who wants to sell their data can see all data pools. Data sellers can choose data pools by checking how many parts of their data to be shared to data buyers. Then, they sign the consents for data exchange. Verified off-chain data validators validate whether data provided by data sellers conforms to criteria that data pool creator has specified. If all the requirements are met, the data is provided to data buyers via secure connections and the promised amount of cryptocurrency is transferred to data sellers. In this entire protocol, data is not recorded on any blockchain such as Panacea. All data transmissions are performed off-chain and Panacea guarantees all agreements for data exchanges and transparent payments. This data exchange protocol is being developed to be as general as possible, so that not only the healthcare data but also all the other types of data can be handled by the protocol. Since Panacea and data exchange protocol is publicly opened, any service providers can build their own services on the top of the data exchange protocol, so that their users can exchange their data securely and get proper rewards. As the first use case, MediBloc is going to build a healthcare data marketplace service based on this protocol. -Well, it sounds like the protocol should work well, right? However, there are many issues that we have to resolve. For privacy and security, data sellers should be able to expose only a small part of their data that is really desired by data buyers. Also, data transmission must be secure, so that no one can steal or intercept the data. In order to guarantee the right of data buyers, all criteria that data buyers specified has to be validated clearly before the payment is finalized. Last but not least, the ecosystem should be attractive enough for many data sellers and buyers to join. +Well, it sounds like the protocol should work well, right? However, there are many issues that we have to resolve. For privacy and security, data providers should be able to expose only a small part of their data that is really desired by data consumers. Also, data transmission must be secure, so that no one can steal or intercept the data. In order to guarantee the right of data consumers, all criteria that data consumers specified has to be validated clearly before the payment is finalized. Last but not least, the ecosystem should be attractive enough for many data providers and consumers to join. In order to resolve these challenges, the team is developing this data exchange protocol with several latest technologies. The detailed tech stack of the data exchange protocol is described in the [Panacea Ecosystem](./0-panacea-ecosystem.md) document. From be07e992e0e22c1b56c26130e86ab9f6fd249df2 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 6 Jan 2023 10:13:06 +0900 Subject: [PATCH 36/84] Update .gitbook/1-users/3-data-exchange/1-consume-data.md Co-authored-by: Hansol Lee <38912532+H4NLee@users.noreply.github.com> --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index c5c5b331..088b14b9 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -43,7 +43,7 @@ panacead query datadeal deals \ ## Query consents -If some data consumers have data that fit the requirements of your data deal, they will submit consents to the chain. +If some data providers have data that fit the requirements of your data deal, they will submit consents to the chain. The consent means that the data provider has agreed to provide their data to a specific data consumer. Also, each consent can contain a data validation certificate issued by an oracle, so that data consumers can trust the validity of data. From 9a04d4861dc21135100246012da2956dd5eb2938 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 6 Jan 2023 10:20:39 +0900 Subject: [PATCH 37/84] revert unintentional changes --- app/export.go | 7 ++-- client/docs/swagger-ui/swagger-ui-bundle.js | 12 +++--- .../swagger-ui-standalone-preset.js | 4 +- client/docs/swagger-ui/swagger.yaml | 38 +++++++++---------- client/docs/swagger_legacy.yaml | 14 +++---- proto/panacea/oracle/v2/query.proto | 4 +- .../cosmos/distribution/v1beta1/query.proto | 8 ++-- .../proto/cosmos/staking/v1beta1/query.proto | 16 ++++---- x/oracle/client/cli/queryOracle.go | 6 +-- x/oracle/types/genesis.pb.go | 2 +- x/oracle/types/oracle.pb.go | 6 +-- x/oracle/types/query.pb.go | 6 +-- x/oracle/types/query.pb.gw.go | 4 +- 13 files changed, 63 insertions(+), 64 deletions(-) diff --git a/app/export.go b/app/export.go index 87dc48b1..a744e549 100644 --- a/app/export.go +++ b/app/export.go @@ -50,8 +50,7 @@ func (app *App) ExportAppStateAndValidators( // prepare for fresh start at zero height // NOTE zero height genesis is a temporary feature which will be deprecated -// -// in favour of export at a block height +// in favour of export at a block height func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) { applyAllowedAddrs := false @@ -103,7 +102,7 @@ func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []str height := ctx.BlockHeight() ctx = ctx.WithBlockHeight(0) - // reinitialize all 4-validators + // reinitialize all validators app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) { // donate any unwithdrawn outstanding reward fraction tokens to the community pool scraps := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, val.GetOperator()) @@ -144,7 +143,7 @@ func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []str return false }) - // Iterate through 4-validators by power descending, reset bond heights, and + // Iterate through validators by power descending, reset bond heights, and // update bond intra-tx counters. store := ctx.KVStore(app.keys[stakingtypes.StoreKey]) iter := sdk.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey) diff --git a/client/docs/swagger-ui/swagger-ui-bundle.js b/client/docs/swagger-ui/swagger-ui-bundle.js index bb1049c0..eb17452a 100644 --- a/client/docs/swagger-ui/swagger-ui-bundle.js +++ b/client/docs/swagger-ui/swagger-ui-bundle.js @@ -22746,7 +22746,7 @@ function h(e) { function n(n, r, i, a, s, l, f) { - (a = a || c, l = l || i, f !== u) && (t && o(!1, "Calling PropTypes 4-validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types")); + (a = a || c, l = l || i, f !== u) && (t && o(!1, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types")); return null == r[i] ? n ? null === r[i] ? new d("The " + s + " `" + l + "` is marked as required in `" + a + "`, but its value is `null`.") : new d("The " + s + " `" + l + "` is marked as required in `" + a + "`, but its value is `undefined`.") : null : e(r, i, a, s, l) } var r = n.bind(null, !1); @@ -31027,7 +31027,7 @@ i = n(269); e.exports = function() { function e(e, t, n, r, a, u) { - u !== i && o(!1, "Calling PropTypes 4-validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types") + u !== i && o(!1, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types") } function t() { @@ -36904,18 +36904,18 @@ i = t.taggedOperations(), a = o("Collapse"); return s.default.createElement("div", null, s.default.createElement("h4", { - className: "0-about-panacea-title" + className: "about-panacea-title" }, "Overview"), i.map(function(e, t) { var o = e.get("operations"), - i = ["0-about-panacea-tags", t], + i = ["about-panacea-tags", t], u = n.isShown(i, !0); return s.default.createElement("div", { - key: "0-about-panacea-" + t + key: "about-panacea-" + t }, s.default.createElement("h4", { onClick: function() { return r.show(i, !u) }, - className: "link 0-about-panacea-tag" + className: "link about-panacea-tag" }, " ", u ? "-" : "+", t), s.default.createElement(a, { isOpened: u, animated: !0 diff --git a/client/docs/swagger-ui/swagger-ui-standalone-preset.js b/client/docs/swagger-ui/swagger-ui-standalone-preset.js index 2e218ec1..f4e8b1a1 100644 --- a/client/docs/swagger-ui/swagger-ui-standalone-preset.js +++ b/client/docs/swagger-ui/swagger-ui-standalone-preset.js @@ -8627,7 +8627,7 @@ function d(t) { function n(n, r, o, u, s, c, l) { - (u = u || f, c = c || o, l !== a) && (e && i(!1, "Calling PropTypes 4-validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types")); + (u = u || f, c = c || o, l !== a) && (e && i(!1, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types")); return null == r[o] ? n ? null === r[o] ? new h("The " + s + " `" + c + "` is marked as required in `" + u + "`, but its value is `null`.") : new h("The " + s + " `" + c + "` is marked as required in `" + u + "`, but its value is `undefined`.") : null : t(r, o, u, s, c) } var r = n.bind(null, !1); @@ -8897,7 +8897,7 @@ o = n(164); t.exports = function() { function t(t, e, n, r, u, a) { - a !== o && i(!1, "Calling PropTypes 4-validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types") + a !== o && i(!1, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types") } function e() { diff --git a/client/docs/swagger-ui/swagger.yaml b/client/docs/swagger-ui/swagger.yaml index d9fabdf9..7dfd809c 100644 --- a/client/docs/swagger-ui/swagger.yaml +++ b/client/docs/swagger-ui/swagger.yaml @@ -2054,7 +2054,7 @@ paths: x-example: cosmos16xyempempp92x9hyzz9wrgf94r6j9h5f06pxxv get: deprecated: true - summary: Query all 4-validators that a delegator is bonded to + summary: Query all validators that a delegator is bonded to tags: - Staking produces: @@ -2531,8 +2531,8 @@ paths: /slashing/signing_infos: get: deprecated: true - summary: Get sign info of given all 4-validators - description: Get sign info of all 4-validators + summary: Get sign info of given all validators + description: Get sign info of all validators produces: - application/json tags: @@ -2567,7 +2567,7 @@ paths: missed_blocks_counter: type: string '400': - description: Invalid validator public key for one of the 4-validators + description: Invalid validator public key for one of the validators '500': description: Internal Server Error '/slashing/validators/{validatorAddr}/unjail': @@ -3011,7 +3011,7 @@ paths: x-example: Param Change description: type: string - x-example: Update max 4-validators + x-example: Update max validators proposer: type: string description: bech32 encoded address @@ -8904,7 +8904,7 @@ paths: - Query '/cosmos/distribution/v1beta1/delegators/{delegator_address}/validators': get: - summary: DelegatorValidators queries the 4-validators of a delegator. + summary: DelegatorValidators queries the validators of a delegator. operationId: DelegatorValidators responses: '200': @@ -13067,7 +13067,7 @@ paths: - Query /cosmos/slashing/v1beta1/signing_infos: get: - summary: SigningInfos queries signing info of all 4-validators + summary: SigningInfos queries signing info of all validators operationId: SigningInfos responses: '200': @@ -13115,7 +13115,7 @@ paths: monitoring their liveness activity. - title: info is the signing info of all 4-validators + title: info is the signing info of all validators pagination: type: object properties: @@ -14693,7 +14693,7 @@ paths: bonded shares multiplied by exchange rate. - description: 4-validators defines the the 4-validators' info of a delegator. + description: validators defines the the validators' info of a delegator. pagination: description: pagination defines the pagination in the response. type: object @@ -16113,7 +16113,7 @@ paths: max_validators: type: integer format: int64 - description: max_validators is the maximum number of 4-validators. + description: max_validators is the maximum number of validators. max_entries: type: integer format: int64 @@ -16540,7 +16540,7 @@ paths: - Query /cosmos/staking/v1beta1/validators: get: - summary: Validators queries all 4-validators that match the given status. + summary: Validators queries all validators that match the given status. operationId: Validators responses: '200': @@ -16861,7 +16861,7 @@ paths: bonded shares multiplied by exchange rate. - description: 4-validators contains all the queried 4-validators. + description: validators contains all the queried validators. pagination: description: pagination defines the pagination in the response. type: object @@ -17074,7 +17074,7 @@ paths: } parameters: - name: status - description: status enables to query for 4-validators matching a given status. + description: status enables to query for validators matching a given status. in: query required: false type: string @@ -36774,7 +36774,7 @@ definitions: type: array items: type: string - description: 4-validators defines the 4-validators a delegator is delegating for. + description: validators defines the validators a delegator is delegating for. description: |- QueryDelegatorValidatorsResponse is the response type for the Query/DelegatorValidators RPC method. @@ -38689,7 +38689,7 @@ definitions: monitoring their liveness activity. - title: info is the signing info of all 4-validators + title: info is the signing info of all validators pagination: type: object properties: @@ -39281,7 +39281,7 @@ definitions: max_validators: type: integer format: int64 - description: max_validators is the maximum number of 4-validators. + description: max_validators is the maximum number of validators. max_entries: type: integer format: int64 @@ -40100,7 +40100,7 @@ definitions: exchange rate. Voting power can be calculated as total bonded shares multiplied by exchange rate. - description: 4-validators defines the the 4-validators' info of a delegator. + description: validators defines the the validators' info of a delegator. pagination: description: pagination defines the pagination in the response. type: object @@ -40526,7 +40526,7 @@ definitions: max_validators: type: integer format: int64 - description: max_validators is the maximum number of 4-validators. + description: max_validators is the maximum number of validators. max_entries: type: integer format: int64 @@ -41472,7 +41472,7 @@ definitions: exchange rate. Voting power can be calculated as total bonded shares multiplied by exchange rate. - description: 4-validators contains all the queried 4-validators. + description: validators contains all the queried validators. pagination: description: pagination defines the pagination in the response. type: object diff --git a/client/docs/swagger_legacy.yaml b/client/docs/swagger_legacy.yaml index 8a6d3169..fe00efa4 100644 --- a/client/docs/swagger_legacy.yaml +++ b/client/docs/swagger_legacy.yaml @@ -754,7 +754,7 @@ paths: x-example: cosmos16xyempempp92x9hyzz9wrgf94r6j9h5f06pxxv get: deprecated: true - summary: Query all 4-validators that a delegator is bonded to + summary: Query all validators that a delegator is bonded to tags: - Staking produces: @@ -803,7 +803,7 @@ paths: /staking/validators: get: deprecated: true - summary: Get all validator candidates. By default it returns only the bonded 4-validators. + summary: Get all validator candidates. By default it returns only the bonded validators. parameters: - in: query name: status @@ -968,7 +968,7 @@ paths: 500: description: Internal Server Error # TODO: We need to either fix this route when the validator is not found or add a slashed validator in the contract tests - # /slashing/4-validators/{validatorPubKey}/signing_info: + # /slashing/validators/{validatorPubKey}/signing_info: # get: # summary: Get sign info of given validator # description: Get sign info of given validator @@ -995,8 +995,8 @@ paths: /slashing/signing_infos: get: deprecated: true - summary: Get sign info of given all 4-validators - description: Get sign info of all 4-validators + summary: Get sign info of given all validators + description: Get sign info of all validators produces: - application/json tags: @@ -1022,7 +1022,7 @@ paths: items: $ref: "#/definitions/SigningInfo" 400: - description: Invalid validator public key for one of the 4-validators + description: Invalid validator public key for one of the validators 500: description: Internal Server Error /slashing/validators/{validatorAddr}/unjail: @@ -1195,7 +1195,7 @@ paths: x-example: "Param Change" description: type: string - x-example: "Update max 4-validators" + x-example: "Update max validators" proposer: $ref: "#/definitions/Address" deposit: diff --git a/proto/panacea/oracle/v2/query.proto b/proto/panacea/oracle/v2/query.proto index 86580e3d..436b12ae 100644 --- a/proto/panacea/oracle/v2/query.proto +++ b/proto/panacea/oracle/v2/query.proto @@ -14,12 +14,12 @@ import "panacea/oracle/v2/genesis.proto"; service Query { // Oracles returns a list of oracles. rpc Oracles(QueryOraclesRequest) returns (QueryOraclesResponse) { - option (google.api.http).get = "/panacea/oracle/v2/5-oracles"; + option (google.api.http).get = "/panacea/oracle/v2/oracles"; } // Oracle returns a oracle. rpc Oracle(QueryOracleRequest) returns (QueryOracleResponse) { - option (google.api.http).get = "/panacea/oracle/v2/5-oracles/{oracle_address}"; + option (google.api.http).get = "/panacea/oracle/v2/oracles/{oracle_address}"; } // OracleRegistrations returns a list of OracleRegistration. diff --git a/third_party/proto/cosmos/distribution/v1beta1/query.proto b/third_party/proto/cosmos/distribution/v1beta1/query.proto index cb9b1839..2991218d 100644 --- a/third_party/proto/cosmos/distribution/v1beta1/query.proto +++ b/third_party/proto/cosmos/distribution/v1beta1/query.proto @@ -19,19 +19,19 @@ service Query { // ValidatorOutstandingRewards queries rewards of a validator address. rpc ValidatorOutstandingRewards(QueryValidatorOutstandingRewardsRequest) returns (QueryValidatorOutstandingRewardsResponse) { - option (google.api.http).get = "/cosmos/distribution/v1beta1/4-validators/" + option (google.api.http).get = "/cosmos/distribution/v1beta1/validators/" "{validator_address}/outstanding_rewards"; } // ValidatorCommission queries accumulated commission for a validator. rpc ValidatorCommission(QueryValidatorCommissionRequest) returns (QueryValidatorCommissionResponse) { - option (google.api.http).get = "/cosmos/distribution/v1beta1/4-validators/" + option (google.api.http).get = "/cosmos/distribution/v1beta1/validators/" "{validator_address}/commission"; } // ValidatorSlashes queries slash events of a validator. rpc ValidatorSlashes(QueryValidatorSlashesRequest) returns (QueryValidatorSlashesResponse) { - option (google.api.http).get = "/cosmos/distribution/v1beta1/4-validators/{validator_address}/slashes"; + option (google.api.http).get = "/cosmos/distribution/v1beta1/validators/{validator_address}/slashes"; } // DelegationRewards queries the total rewards accrued by a delegation. @@ -49,7 +49,7 @@ service Query { // DelegatorValidators queries the validators of a delegator. rpc DelegatorValidators(QueryDelegatorValidatorsRequest) returns (QueryDelegatorValidatorsResponse) { option (google.api.http).get = "/cosmos/distribution/v1beta1/delegators/" - "{delegator_address}/4-validators"; + "{delegator_address}/validators"; } // DelegatorWithdrawAddress queries withdraw address of a delegator. diff --git a/third_party/proto/cosmos/staking/v1beta1/query.proto b/third_party/proto/cosmos/staking/v1beta1/query.proto index 42db4254..4852c535 100644 --- a/third_party/proto/cosmos/staking/v1beta1/query.proto +++ b/third_party/proto/cosmos/staking/v1beta1/query.proto @@ -12,36 +12,36 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/staking/types"; service Query { // Validators queries all validators that match the given status. rpc Validators(QueryValidatorsRequest) returns (QueryValidatorsResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators"; + option (google.api.http).get = "/cosmos/staking/v1beta1/validators"; } // Validator queries validator info for given validator address. rpc Validator(QueryValidatorRequest) returns (QueryValidatorResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/{validator_addr}"; + option (google.api.http).get = "/cosmos/staking/v1beta1/validators/{validator_addr}"; } // ValidatorDelegations queries delegate info for given validator. rpc ValidatorDelegations(QueryValidatorDelegationsRequest) returns (QueryValidatorDelegationsResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/{validator_addr}/delegations"; + option (google.api.http).get = "/cosmos/staking/v1beta1/validators/{validator_addr}/delegations"; } // ValidatorUnbondingDelegations queries unbonding delegations of a validator. rpc ValidatorUnbondingDelegations(QueryValidatorUnbondingDelegationsRequest) returns (QueryValidatorUnbondingDelegationsResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/" + option (google.api.http).get = "/cosmos/staking/v1beta1/validators/" "{validator_addr}/unbonding_delegations"; } // Delegation queries delegate info for given validator delegator pair. rpc Delegation(QueryDelegationRequest) returns (QueryDelegationResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/{validator_addr}/delegations/" + option (google.api.http).get = "/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/" "{delegator_addr}"; } // UnbondingDelegation queries unbonding info for given validator delegator // pair. rpc UnbondingDelegation(QueryUnbondingDelegationRequest) returns (QueryUnbondingDelegationResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/4-validators/{validator_addr}/delegations/" + option (google.api.http).get = "/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/" "{delegator_addr}/unbonding_delegation"; } @@ -66,13 +66,13 @@ service Query { // DelegatorValidators queries all validators info for given delegator // address. rpc DelegatorValidators(QueryDelegatorValidatorsRequest) returns (QueryDelegatorValidatorsResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/delegators/{delegator_addr}/4-validators"; + option (google.api.http).get = "/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators"; } // DelegatorValidator queries validator info for given delegator validator // pair. rpc DelegatorValidator(QueryDelegatorValidatorRequest) returns (QueryDelegatorValidatorResponse) { - option (google.api.http).get = "/cosmos/staking/v1beta1/delegators/{delegator_addr}/4-validators/" + option (google.api.http).get = "/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators/" "{validator_addr}"; } diff --git a/x/oracle/client/cli/queryOracle.go b/x/oracle/client/cli/queryOracle.go index 5331e424..ae792ace 100644 --- a/x/oracle/client/cli/queryOracle.go +++ b/x/oracle/client/cli/queryOracle.go @@ -9,8 +9,8 @@ import ( func CmdGetOracles() *cobra.Command { cmd := &cobra.Command{ - Use: "5-oracles", - Short: "Query 5-oracles info", + Use: "oracles", + Short: "Query oracles info", RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { @@ -37,7 +37,7 @@ func CmdGetOracles() *cobra.Command { } flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "5-oracles") + flags.AddPaginationFlagsToCmd(cmd, "oracles") return cmd } diff --git a/x/oracle/types/genesis.pb.go b/x/oracle/types/genesis.pb.go index 3134bff0..e36006ed 100644 --- a/x/oracle/types/genesis.pb.go +++ b/x/oracle/types/genesis.pb.go @@ -26,7 +26,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the oracle module's genesis state. type GenesisState struct { - Oracles []Oracle `protobuf:"bytes,1,rep,name=5-oracles,proto3" json:"5-oracles"` + Oracles []Oracle `protobuf:"bytes,1,rep,name=oracles,proto3" json:"oracles"` OracleRegistrations []OracleRegistration `protobuf:"bytes,2,rep,name=oracle_registrations,json=oracleRegistrations,proto3" json:"oracle_registrations"` Params Params `protobuf:"bytes,3,opt,name=params,proto3" json:"params"` } diff --git a/x/oracle/types/oracle.pb.go b/x/oracle/types/oracle.pb.go index ca9dba92..1d9ff844 100644 --- a/x/oracle/types/oracle.pb.go +++ b/x/oracle/types/oracle.pb.go @@ -105,14 +105,14 @@ type OracleRegistration struct { UniqueId string `protobuf:"bytes,1,opt,name=unique_id,json=uniqueId,proto3" json:"unique_id,omitempty"` OracleAddress string `protobuf:"bytes,2,opt,name=oracle_address,json=oracleAddress,proto3" json:"oracle_address,omitempty"` // Node public key is a pair with a node private key which is generated in SGX by each oracle. - // This key is used to share the oracle private key from other 5-oracles. + // This key is used to share the oracle private key from other oracles. NodePubKey []byte `protobuf:"bytes,3,opt,name=node_pub_key,json=nodePubKey,proto3" json:"node_pub_key,omitempty"` // Anyone can validate that the node key pair is generated in SGX using this node key remote report. NodePubKeyRemoteReport []byte `protobuf:"bytes,4,opt,name=node_pub_key_remote_report,json=nodePubKeyRemoteReport,proto3" json:"node_pub_key_remote_report,omitempty"` // A newly joining oracle must report a trusted block info which was used to initialize its light client. - // Other 5-oracles will validate whether this trusted block info is correct, + // Other oracles will validate whether this trusted block info is correct, // in order to prevent malicious operators from making the oracle look at a malicious chain node. - // Other 5-oracles don't have to worry about whether this block info was set by a malicious operator, + // Other oracles don't have to worry about whether this block info was set by a malicious operator, // because this message has to be generated inside SGX. // Also, after this oracle registration is complete, the light client is protected from malicious operators by SGX. TrustedBlockHeight int64 `protobuf:"varint,5,opt,name=trusted_block_height,json=trustedBlockHeight,proto3" json:"trusted_block_height,omitempty"` diff --git a/x/oracle/types/query.pb.go b/x/oracle/types/query.pb.go index fe21ab7e..8aea2f34 100644 --- a/x/oracle/types/query.pb.go +++ b/x/oracle/types/query.pb.go @@ -78,7 +78,7 @@ func (m *QueryOraclesRequest) GetPagination() *query.PageRequest { // QueryOracleResponse is the response type for the Query/Oracles RPC method. type QueryOraclesResponse struct { - Oracles []*Oracle `protobuf:"bytes,1,rep,name=5-oracles,proto3" json:"5-oracles,omitempty"` + Oracles []*Oracle `protobuf:"bytes,1,rep,name=oracles,proto3" json:"oracles,omitempty"` Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` } @@ -579,7 +579,7 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type QueryClient interface { - // Oracles returns a list of 5-oracles. + // Oracles returns a list of oracles. Oracles(ctx context.Context, in *QueryOraclesRequest, opts ...grpc.CallOption) (*QueryOraclesResponse, error) // Oracle returns a oracle. Oracle(ctx context.Context, in *QueryOracleRequest, opts ...grpc.CallOption) (*QueryOracleResponse, error) @@ -646,7 +646,7 @@ func (c *queryClient) Params(ctx context.Context, in *QueryOracleParamsRequest, // QueryServer is the server API for Query service. type QueryServer interface { - // Oracles returns a list of 5-oracles. + // Oracles returns a list of oracles. Oracles(context.Context, *QueryOraclesRequest) (*QueryOraclesResponse, error) // Oracle returns a oracle. Oracle(context.Context, *QueryOracleRequest) (*QueryOracleResponse, error) diff --git a/x/oracle/types/query.pb.gw.go b/x/oracle/types/query.pb.gw.go index c39ff91b..74beaae5 100644 --- a/x/oracle/types/query.pb.gw.go +++ b/x/oracle/types/query.pb.gw.go @@ -538,9 +538,9 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Oracles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"panacea", "oracle", "v2", "5-oracles"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Oracles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"panacea", "oracle", "v2", "oracles"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_Oracle_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"panacea", "oracle", "v2", "5-oracles", "oracle_address"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Oracle_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"panacea", "oracle", "v2", "oracles", "oracle_address"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_OracleRegistrations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"panacea", "oracle", "v2", "oracle-registrations", "unique_id"}, "", runtime.AssumeColonVerbOpt(true))) From 984539febe5f83078ef5f1368d8ded8f54e1ee8c Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 6 Jan 2023 10:36:17 +0900 Subject: [PATCH 38/84] add jwt guide --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 088b14b9..21da67d8 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -75,11 +75,18 @@ Using the following REST API, you can get a secret key of each data from the ora curl -v -X GET -H "Authorization: Bearer ${jwt}" \ "${oracle-url}/v0/data-deal/secret-key?deal-id=${deal-id}&data-hash=${data-hash}" ``` -You must specify a JWT issued by yourself in order to prove that you are the data consumer who created the data deal. +You must specify a JWT issued using your account key in order to prove that you are the data consumer who created the data deal. For this authentication, the JWT must be signed by your (data consumer's) chain account private key. We highly recommend to set the expiration of JWT as short as possible for security reasons. +You can use the `panacead` CLI to issue JWTs easily by the following command. In near future, the protocol will adopt the 'nonce' concept to improve the security of authentications. +```bash +panacead issue-jwt ${expiration-duration} --from ${your-account-key-name} + +# e.g. +# panacead issue-jwt 10s --from panacea1zqum... +``` Please note that the returned secret key is also encrypted, so that only the specific data consumers can decrypt the key using his/her chain account private key. Nevertheless, we highly recommend you to communicate with oracles who provides an HTTPS endpoint with SSL/TLS encryption. From 9dd634eb3a4f07a90fb2eb9a4b8fb2ffb54a2183 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee Date: Fri, 6 Jan 2023 12:30:08 +0900 Subject: [PATCH 39/84] deal json --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 21da67d8..26337d3d 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -19,7 +19,15 @@ panacead tx datadeal create-deal ${deal-file-path} \ For `deal-file-path`, create a following JSON file. ```json { - + "data_schema": [ + "http://jsonschema.gopanacea.org/vaccination-cert.json" + ], + "budget": { + "denom": "umed", + "amount": "1000000" + }, + "max_num_data": 10, + "consumer_address": "panacea1..." } ``` It is very important to set data schema specifically and correctly, so that data being provided can be validated accurately by oracles. From f62e72e40245013c78218dc5f50a873b93d4d718 Mon Sep 17 00:00:00 2001 From: H4NLee Date: Fri, 6 Jan 2023 14:38:27 +0900 Subject: [PATCH 40/84] docs: rename buyer and seller --- .gitbook/0-about-panacea/1-roadmap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/0-about-panacea/1-roadmap.md b/.gitbook/0-about-panacea/1-roadmap.md index cad895e6..976821b3 100644 --- a/.gitbook/0-about-panacea/1-roadmap.md +++ b/.gitbook/0-about-panacea/1-roadmap.md @@ -8,7 +8,7 @@ Now, MediBloc would like to shift its focus to boosting the potential of Panacea Nowadays, many businesses and technologies are data-driven. Many companies are already familiar with handling large dataset and deriving new values by analyzing sets of data. But, secure data exchange is still the one of the hardest area for data-driven industries. Data requesters want well-refined data or fine-grained raw data for successful data analysis. But, data owners (individuals) don’t want their privacy exposed and abused. Additionally, Web3 users are already aware that proper rewards should be guaranteed for their data and actions transparently on Web3. Traditional systems in Web2 have solved this issue in various ways, but MediBloc believes that we all can build more transparent and reliable systems for secure data exchange in Web3 ecosystem. -Our data exchange protocol has the concept of data Pool, so that anyone can specify the type and the quantity of the data they want. Also, they can specify how much cryptocurrency they are willing to pay for the data. All of these data pools are recorded in Panacea and everyone who wants to sell their data can see all data pools. Data sellers can choose data pools by checking how many parts of their data to be shared to data buyers. Then, they sign the consents for data exchange. Verified off-chain data validators validate whether data provided by data sellers conforms to criteria that data pool creator has specified. If all the requirements are met, the data is provided to data buyers via secure connections and the promised amount of cryptocurrency is transferred to data sellers. In this entire protocol, data is not recorded on any blockchain such as Panacea. All data transmissions are performed off-chain and Panacea guarantees all agreements for data exchanges and transparent payments. +Our data exchange protocol has the concept of data Pool, so that anyone can specify the type and the quantity of the data they want. Also, they can specify how much cryptocurrency they are willing to pay for the data. All of these data pools are recorded in Panacea and everyone who wants to sell their data can see all data pools. Data providers can choose data pools by checking how many parts of their data to be shared to data consumers. Then, they sign the consents for data exchange. Verified off-chain data validators validate whether data provided by data providers conforms to criteria that data pool creator has specified. If all the requirements are met, the data is provided to data consumers via secure connections and the promised amount of cryptocurrency is transferred to data providers. In this entire protocol, data is not recorded on any blockchain such as Panacea. All data transmissions are performed off-chain and Panacea guarantees all agreements for data exchanges and transparent payments. This data exchange protocol is being developed to be as general as possible, so that not only the healthcare data but also all the other types of data can be handled by the protocol. Since Panacea and data exchange protocol is publicly opened, any service providers can build their own services on the top of the data exchange protocol, so that their users can exchange their data securely and get proper rewards. As the first use case, MediBloc is going to build a healthcare data marketplace service based on this protocol. Well, it sounds like the protocol should work well, right? However, there are many issues that we have to resolve. For privacy and security, data providers should be able to expose only a small part of their data that is really desired by data consumers. Also, data transmission must be secure, so that no one can steal or intercept the data. In order to guarantee the right of data consumers, all criteria that data consumers specified has to be validated clearly before the payment is finalized. Last but not least, the ecosystem should be attractive enough for many data providers and consumers to join. From 39daf845481e715b70824daab7b120d81e3f0b26 Mon Sep 17 00:00:00 2001 From: audtlr24 Date: Mon, 9 Jan 2023 16:39:39 +0900 Subject: [PATCH 41/84] docs: add list of operating oracle nodes --- .gitbook/5-oracles/1-operate-oracle-nodes/0-overview.md | 0 .../5-oracles/1-operate-oracle-nodes/1-oracle-installation.md | 0 .../5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md | 0 .gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md | 0 .../5-oracles/1-operate-oracle-nodes/4-oracle-registration.md | 0 .gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md | 0 .gitbook/5-oracles/1-operate-oracle-nodes/6-upgrading-node.md | 0 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/0-overview.md create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/6-upgrading-node.md diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/0-overview.md b/.gitbook/5-oracles/1-operate-oracle-nodes/0-overview.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md b/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md b/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md b/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md b/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md b/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md new file mode 100644 index 00000000..e69de29b diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/6-upgrading-node.md b/.gitbook/5-oracles/1-operate-oracle-nodes/6-upgrading-node.md new file mode 100644 index 00000000..e69de29b From a8d0a7beda4749e659bed2d7d6e9f0a1e917db03 Mon Sep 17 00:00:00 2001 From: audtlr24 Date: Mon, 9 Jan 2023 16:46:38 +0900 Subject: [PATCH 42/84] docs: add operate oracle nodes to SUMMARY.md --- .gitbook/SUMMARY.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index 6311f10a..b9e98813 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -63,4 +63,11 @@ * [About DEP Oracle](5-oracles/0-about-dep-oracle.md) * Operate Oracle Nodes + * [Overview](5-oracles/1-operate-oracle-nodes/0-overview.md) + * [Oracle Installation](5-oracles/1-operate-oracle-nodes/1-oracle-installation.md) + * [Oracle Initialization](5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md) + * [Genesis Oracle](5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md) + * [Oracle Registration](5-oracles/1-operate-oracle-nodes/4-oracle-registration.md) + * [Running a Node](5-oracles/1-operate-oracle-nodes/5-running-node.md) + * [Upgrading a Node](5-oracles/1-operate-oracle-nodes/6-upgrading-node.md) * FAQ \ No newline at end of file From 05f1204612ddef2bd96bb993e1fd36d7095864dc Mon Sep 17 00:00:00 2001 From: gyuguen Date: Mon, 9 Jan 2023 19:01:53 +0900 Subject: [PATCH 43/84] docs: add data validation spec for protocol devs (#596) --- .../1-dep-specs/4-data-validation.md | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md b/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md index e69de29b..037f2488 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md @@ -0,0 +1,201 @@ +# Data validation + +- Status: Draft +- Created: 2023-01-04 +- Modified: 2023-01-04 +- Authors + - Gyuguen Jang + - Youngjoon Lee + - Hansol Lee + - Myongsik Gong + - Inchul Song + + +## Synopsis + +This document describes the API specification, data verification, and process for issuing certificates. + +### Motivation +Data consumers can define their requirements. +This requirement allows them to define the data in any format they want. +DEP supports a `JSON schema` to define these requirements. +Oracle can verify the requirements of data consumers according to this JSON schema specification. +Oracle issues a certificate upon successful verification, which can be verified by Panacea. + +### Definitions +`Data Provider`, `Data Consumer`, and `Oracle` and [JSON schema](https://www.w3.org/2019/wot/json-schema) + +## Technical Specification + +### API Specification + +#### Request URI +```http request +POST /v0/data-deal/deals/{dealID}/data +``` + +#### Request Headers +``` +# Authorization: Bearer {jwtToken} +# Content-Type: application/json +``` + +TODO: Guide to JWT generate and verify + +#### Request Body +``` +{ + "provider_address": "panacea1ewugvs354xput6xydl5cd5tvkzcuymkejekwk3", + "encrypted_data_base64": "3TpdyLXP0xObMWYev8XwqlKjxzWsP5OiQQjq6MooWUwiP37JGqFgl8Rv+a43RMoNieSmBml2AeE1M3sIn39T3R3FD5nqOcFx2MbsnUYHMVASzv5mv53EYx+mP/aPl7pTeMCioQkRqXCyNrj+EJVQEoUdt2DgJwstia3O5pFFRUViKdVJsGIpDX8vY7qQdNuId/beVqWpL5ffSayZnQg=", + "data_hash": "13341f91f0da76d2adb67b519e2c9759822ceafd193bd26435ba0d5eee4c3a2b" +} +``` +| Key | Type | Description | +|-----------------------|--------|------------------------------------------------------------------| +| provider_address | string | Data provider's account address | +| encrypted_data_base64 | string | Base64-encoded value after encrypt the original data | +| data_hash | string | A hexadecimal string of a SHA256 hash value of the original data | + +#### Response Headers +``` +# Content-Type: application/json +``` + +#### ResponseBody +```json +{ + "unsigned_certificate": { + "cid": "QmeSiVLXWagUv9sLEHvbsUJy8rm7r5BoP2pAXrbx4pdbWi", + "unique_id": "9a3da3162aa592af3c77f1bba2d5635c7b4c065249bd36094fe3c11c73c90618", + "oracle_address": "panacea1ewugvs354xput6xydl5cd5tvkzcuymkejekwk3", + "deal_id": 1, + "provider_address": "panacea1ewugvs354xput6xydl5cd5tvkzcuymkejekwk3", + "data_hash": "13341f91f0da76d2adb67b519e2c9759822ceafd193bd26435ba0d5eee4c3a2b" + }, + "signature": "MEQCIEPyGSe9wVIjrUFuzXtQtEc0siwaHkp4QJCMBvC8ttWQAiAUkntIQldgIkIBFdthaTRWXHisDV2Ys/Ufpc9zejUEuQ==" +} +``` + +| Key | Type | Description | +|---------------------------------------|--------|------------------------------------------------------------------------------| +| unsigned_certificate | Object | Unsigned certificate containing data validation information | +| unsigned_certificate.cid | string | A content identifier of a file in IPFS | +| unsigned_certificate.unique_id | string | UniqueID of the oracle that validated the data | +| unsigned_certificate.oracle_address | string | Account address of the oracle that validated the data | +| unsigned_certificate.deal_id | uint | Deal to whom the provider intends to provide data | +| unsigned_certificate.provider_address | string | Data provider's account address | +| unsigned_certificate.data_hash | string | A hexadecimal string of a SHA256 hash value of the original data | +| signature | string | Base64-encoded string signed `unsigned_certificate` with Oracle private key. | + + +### Data validation process + +#### Data Decryption +Provider's encrypted data(`encrypted_data_base64`) can only be decrypted by oracle. + +``` +secret_key = SHA256(ECDH(oracle_private_key, provider_public_key)) + +encrypted_data = Base64.Decode(encrypted_data_base64) + +orginal_data = AES256GCM.Decrypt(secret_key, encrypted_data) +``` + +#### Data Validation +Verify that the original data matches the `data_hash`. +``` +compare(data_hash, Hex.Encode(SHA256(orginal_data)) +``` + +Verify that the `provider_address` of the original data matches the JWT auth token issuer of the request header. +``` +compare(provider_address, jwtToken.issuer) +``` + +The deal information can be retrieved from Panacea using the deal ID + +Before verifying the data, it is checked whether the deal status is valid. +If the Deal's status is invalid, oracle does not perform verification work. +``` +compare(deal.status, 'DEAL_STATUS_ACTIVE') +``` + +Validate original data with `data_schema` extracted from Deal. +We currently support JSON schema. +``` +data_schema = deal.data_schema + +JSONSchema.Validate(data_schema, orginal_data) +``` + +#### Data re-encryption and delivery via IPFS + +If data validation is successful, the data must be re-encrypted and stored on IPFS to be delivered to the consumer. + +To re-encrypt the data, a symmetric secret key must be used. The symmetric secret key can be derived by the following logic. +``` +deal_id_bz = convertUint64ToBigEndian(deal_id) +secret_key = SHA256(append(oracle_private_key, deal_id_bz, data_hash)) +``` + +After encrypting the data with the generated `secretKey`, store it to IPFS. + +``` +encrypted_data = AES256GCM.Encrypt(secret_key, orginal_data) + +cid = IPFS.add(encrypted_data) +``` + + +#### Certificate issuance with a cryptographic signature +If all processes succeed, oracle responds to the Provider by issuing a certificate. + +The certificate includes the following contents. +```json +{ + "unsigned_certificate": { + "cid": "QmeSiVLXWagUv9sLEHvbsUJy8rm7r5BoP2pAXrbx4pdbWi", + "unique_id": "9a3da3162aa592af3c77f1bba2d5635c7b4c065249bd36094fe3c11c73c90618", + "oracle_address": "panacea1ewugvs354xput6xydl5cd5tvkzcuymkejekwk3", + "deal_id": 1, + "provider_address": "panacea1ewugvs354xput6xydl5cd5tvkzcuymkejekwk3", + "data_hash": "13341f91f0da76d2adb67b519e2c9759822ceafd193bd26435ba0d5eee4c3a2b" + }, + "signature": "MEQCIEPyGSe9wVIjrUFuzXtQtEc0siwaHkp4QJCMBvC8ttWQAiAUkntIQldgIkIBFdthaTRWXHisDV2Ys/Ufpc9zejUEuQ==" +} +``` + +The certificate requires a signature signed with `oracle_private_key`. +Because Panacea needs to be able to verify that the certificate was generated by a trusted oracle. +The `oracle_public_key` registered in Panacea is a pair with the `oracle_private_key` of a trusted oracle. +So, Panacea can verify signature of the certificate with `oracle_public_key` to ensure that the certificate is correct. + +Signature is a value obtained by signing `unsigned_certificate` with `oracle_private_key`. +``` +signature = sign(oracle_private_key, unsigned_certificate) +``` + + +## Backwards Compatibility + +Not applicable. + +## Forwards Compatibility + +If the JSON-LD validation specification is applied in the future, oracle will also be support. + +## Example Implementations + +TODO: Repo URLs of panacea-core and panacea-oracle with specific tags + +## Other Implementations + +None at present. + +## History + +- 2023-01-04: Initial draft finished + +## Copyright + +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file From a151c117514364d95688a9af85cd22fddaa95e5c Mon Sep 17 00:00:00 2001 From: Hansol Lee <38912532+H4NLee@users.noreply.github.com> Date: Tue, 10 Jan 2023 09:23:18 +0900 Subject: [PATCH 44/84] docs: add data provider consent spec for protocol devs (#592) --- .../1-dep-specs/3-data-provider-consent.md | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md index e69de29b..72a99850 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md @@ -0,0 +1,96 @@ +# Data Provider Consent + +- Status: Draft +- Crated: 2023-01-04 +- Modified: 2023-01-04 +- Authors + - Youngjoon Lee + - Gyuguen Jang + - Hansol Lee + - Myongsik Gong + - Inchul Song + + +## Synopsis + +This document is about providing data through [DEP](../../1-users/3-data-exchange/0-about-dep.md). +Before providers provide their data to consumers, the data must be validated from oracle whether the data is the correct data specified in the deal. +Providers can send a request for validation to one of the oracles registered in Panacea, and the oracle will validate the data using confidential computing without any exposure of the data. +As a result of a data validation, oracle will issue a certificate to the provider. +Providers can consent to provide their data by submitting the certificate to Panacea, and will be rewarded by providing the data. +In all of these processes, the data is transmitted with encryption and stored off-chain. + +### Motivation + +Data should be provided by providers based on their data ownership, and the reward should be distributed in transparent and fair manner. +To do so, providers use digital signature as consent to provide the data. + +### Definitions + +- `Data Provider`, `Data Consumer`, and `Oracle` are defined in [User Flow](./1-user-flow.md) +- `Deal` is defined in [Data Deal](./2-data-deal.md) +- `Certificate`: a certificate that the data is validated to be provided to the deal, which is issued by oracle. + +## Technical Specification + +Before provider provides the data to deal, data should be validated by the oracle. +If the data is successfully validated to be provided, the provider will have a `Certificate` like below (more about [Data Validation](./4-data-validation.md)): + +```proto +message Certificate { + UnsignedCertificate unsigned_certificate = 1; + bytes signature = 2; +} + +message UnsignedCertificate { + string cid = 1; + string unique_id = 2; + string oracle_address = 3; + uint64 deal_id = 4; + string provider_address = 5; + string data_hash = 6; +} +``` + +Using the `Certificate`, provider can submit consent to provide the data. + +```proto +message MsgSubmitConsent { + Consent consent = 1; +} + +message Consent { + Certificate certificate = 1; +} +``` + +When this consent is submitted, blockchain will check: +- if the data is provided by the owner of the data +- if the data is validated by a registered and active oracle +- if the data is provided in duplicate + +If all checks pass, rewards are distributed to the provider and oracle(more about [incentive](./6-incentives.md)). + +## Backwards Compatibility + +Not applicable. + +## Forwards Compatibility + +Not applicable. + +## Example Implementations + +Coming soon. + +## Other Implementations + +None at present. + +## History + +- 2023-01-04: Initial draft finished + +## Copyright + +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file From d4976bd0a6d9b0909a7b263e9f30055bce8e65c1 Mon Sep 17 00:00:00 2001 From: audtlr24 Date: Tue, 10 Jan 2023 10:49:07 +0900 Subject: [PATCH 45/84] docs: add user guide for provider (#594) Co-authored-by: InChul <49394875+inchori@users.noreply.github.com> --- .../1-users/3-data-exchange/2-provide-data.md | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/.gitbook/1-users/3-data-exchange/2-provide-data.md b/.gitbook/1-users/3-data-exchange/2-provide-data.md index e827d666..c58527b3 100644 --- a/.gitbook/1-users/3-data-exchange/2-provide-data.md +++ b/.gitbook/1-users/3-data-exchange/2-provide-data.md @@ -1 +1,97 @@ -# Consume data +# Provide data + +Data providers can provide their data that match the requirements of the data deal and in return earn a reward. + +Since only the data verified by oracle can be provided to a deal, providers should first request data verification to oracle. + +As a result of verification, oracle will issue a certificate, then provider can provide their data by submitting a consent with the certificate to Panacea. + +In the whole process of data transmission, the data is encrypted so that no one can access the original data. + +The transmission of data and the payment of rewards are managed atomically through the Panacea, so consumers can get the data only when the reward payment is completed. + +## Request data verification to oracle + +Before request to oracle, you should encrypt your data for privacy preserving. +Encryption can be done using your chain account key and oracle public key which is registered in Panacea. +This makes only oracles can decrypt and verify your original data in secure area. +For more details about data secure area, please see [Confidential Oracle](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md). + +You can encrypt data by the following CLI: +```bash +panacead encrypt-data ${input-file-path} ${your-account-key-name} +``` + +You must specify a JWT issued by yourself in order to prove that you are the data provider. +For that authentication, the JWT must be signed by your (data provider's) chain account private key. + +We highly recommend to set the expiration of JWT as short as possible for security reasons. +In the near future, the protocol will adopt the 'nonce' concept to improve the security of authentications. + +You can issue JWT by the following CLI: +```bash +panacead issue-jwt ${expiration-duration} --from ${your-account-key-name} + +# e.g. +# panacead issue-jwt 10s --from panacea1zqum... +``` + +Using the following REST API, you can post encrypted data to oracle for verification with deal ID you want to provide. +```bash +curl -v -X POST -H "Authorization: Bearer ${jwt}" ${oracle-url}/v0/data-deal/deals/${deal-id}/data -d ${encrpyted-data-json-path} +``` + +For `encrpyred-data-json`, create a following JSON file. +```json +{ + "provider_address" : "{your-address}", + "data_hash" : "{data-hash-of-original-data}", + "encrypted_data_base64" : "{encrypted-data}" +} +``` +You have to use data hash of original data with SHA-256 hash function. For example, you can get hash by following CLI: +```bash +sha256sum ${original-data-path} +``` + +Through this process, the data is safely and securely transmitted to oracle, and the oracle verifies the data hash and data schema. +For more details about oracle data validation, please see the [Data Validation](../../3-protocol-devs/1-dep-specs/4-data-validation.md) specification. + +When the verification is completed, you can get a data certificate that includes the oracle's signature. +The certificate form is like below: +```json +{ + "unsigned_certificate" : { + "cid" : "{ipfs-cid}", + "unique_id" : "{oracle-unique-id}", + "oracle_address" : "{oracle-address}", + "deal_id": "{deal-id}", + "provider_address" : "{your-address}", + "data_hash" : "{data-hash}" + }, + "signature" : "{oracle-signature}" +} +``` +Now you can use this certificate in the next step. + +## Submit consent + +Broadcast the following `submit-consent` transaction with certificate from oracle. +```bash +panacead submit-consent ${certificate-file-path} \ + --from ${data-provider-addr} \ + --chain-id ${chain-id} \ + --gas auto --gas-adjustment 1.30 --gas-prices 5umed \ + --node ${chain-node-rpc-addr} +``` + +After you submit consent, Panacea verifies the certificate and checks the status of the deal. + +When the verification is completed, Panacea makes the data accessible to consumers and makes you can get reward. + +## Query consent +You can query a consent by the deal ID and data hash you provided. +```bash +panacead query datadeal consent ${deal-id} ${data-hash} \ + --node ${chain-node-rpc-addr} +``` \ No newline at end of file From e2cdd32683f094dfe097a6d463d4599114e34522 Mon Sep 17 00:00:00 2001 From: Hansol Lee <38912532+H4NLee@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:31:59 +0900 Subject: [PATCH 46/84] docs: incentives for protocol devs (#601) --- .../1-dep-specs/4-data-validation.md | 2 +- .../1-dep-specs/6-incentives.md | 81 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md b/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md index 037f2488..7dc2d27c 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md @@ -61,7 +61,7 @@ TODO: Guide to JWT generate and verify # Content-Type: application/json ``` -#### ResponseBody +#### Response Body ```json { "unsigned_certificate": { diff --git a/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md b/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md index e69de29b..7985eda7 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md @@ -0,0 +1,81 @@ +# Incentives + +- Status: Draft +- Created: 2023-01-06 +- Modified: 2023-01-06 +- Authors + - Youngjoon Lee + - Gyuguen Jang + - Hansol Lee + - Myongsik Gong + - Inchul Song + + +## Synopsis + +When data deal is created, a budget for data is deposited from data consumer account. +And the deposit is distributed to the data providers and the oracles that verified the data. +Data consumers also can [deactivate the deal](./2-data-deal.md#Deactivate-Data-Deal) they created and refund the remaining budget at any time if the deal is in status `DEAL_STATUS_ACTIVE`. + +### Motivation + +This is for transparent distribution for the cost of providing data and the cost of verifying data. + +### Definitions + +`Data Provider`, `Data Consumer` and `Oracle` are defined in [User Flow](./1-user-flow.md) + +## Technical Specification + +### Budget Deposit + +When data consumers [create a deal](./2-data-deal.md#create-data-deal), they specify the budget for data provision. +At this time, the amount of the budget is transferred from consumer account to deal account. + +### Reward Distribution + +When creating a data deal, data consumers specify the quantity as well as the budget for the data. +From this, the price per data can be calculated as: + +``` +price_per_data = deposit / max_num_data +``` + +Of the `price_per_data`, as an oracle commission for data verification, the commission rate set by the oracle is transferred to the oracle, and the rest is transferred to the data provider. + +The oracle commission can be set differently for each oracle. +you can find out which oracle verified the data by referring to the [certificate](./4-data-validation.md#Response-Body) submitted by the data provider and how much commission fee to be paid. + +``` +oracle_reward = price_per_data * oracle_commission_rate +provider_reward = price_per_data * (1 - oracle_commission_rate) +``` + +### Budget Refund + +If consumers want to stop being provided data and refund for the rest of their budget, they can deactivate the deal they created. +However, in order to deactivate the deal, the deal must be in the `DEAL_STATUS_ACTIVE` state. + +## Backwards Compatibility + +Not applicable. + +## Forwards Compatibility + +Not applicable. + +## Example Implementations + +Coming soon. + +## Other Implementations + +None at present. + +## History + +- 2023-01-06: Initial draft finished + +## Copyright + +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file From 5b439338f97635e3b71f79abdf23d48d298ff0f1 Mon Sep 17 00:00:00 2001 From: audtlr24 Date: Thu, 12 Jan 2023 17:01:40 +0900 Subject: [PATCH 47/84] docs: add oracle installation (#607) --- .../1-oracle-installation.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md b/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md index e69de29b..ef52558a 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md @@ -0,0 +1,43 @@ +# Installation + +## Hardware Requirement + +The oracle only works on [SGX](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/overview.html)-[FLC](https://github.com/intel/linux-sgx/blob/master/psw/ae/ref_le/ref_le.md) environment with a [quote provider](https://docs.edgeless.systems/ego/#/reference/attest) installed. +You can check if your hardware supports SGX, and it is enabled in the BIOS by following [EGo guide](https://docs.edgeless.systems/ego/#/getting-started/troubleshoot?id=hardware). + +## Installation: Use Docker + +### Pull an image +You can pull docker image by following CLI: +```bash +docker pull ghcr.io/medibloc/panacea-oracle:latest +``` +It is highly recommended to use a specific Docker image tag instead of `latest`. +You can find image tags from the [GitHub Packages page](https://github.com/medibloc/panacea-oracle/pkgs/container/panacea-oracle). + +### Run a container using SGX +This is a sample command to show you how to run a container using SGX in your host. +```bash +docker run \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v ${ANY_DIR_ON_HOST}:/oracle \ + ghcr.io/medibloc/panacea-oracle:latest \ + ego run /usr/bin/oracled --help +``` +After successful installation, go to the process of [initializing oracle](5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md). + + +### How about building from source? + +You can build from source by referring to the following [installation-from-source](https://github.com/medibloc/panacea-oracle/blob/main/docs/installation-src.md). + +However, we highly recommend installing using docker. +This is because the uniqueID in `EGo` is sensitively changes depending on the Go dependency or local debug environment. + +Therefore, it is recommended that you check the uniqueID with following CLI when you want to use the binary you built yourself. +```bash +ego sign ${enclave-json-path} # docker image use enclave in /scripts/enclave-prod.json +ego uniqueid ${oracle-binary-path} +``` + From 4efe3032f3287e8021d90d48d7673a223d332b07 Mon Sep 17 00:00:00 2001 From: Hansol Lee <38912532+H4NLee@users.noreply.github.com> Date: Thu, 12 Jan 2023 17:54:13 +0900 Subject: [PATCH 48/84] docs: oracle-registration for oracle operators (#609) --- .../4-validators/3-join-mainnet-testnet.md | 2 +- .../4-oracle-registration.md | 111 ++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/.gitbook/4-validators/3-join-mainnet-testnet.md b/.gitbook/4-validators/3-join-mainnet-testnet.md index 5837dce4..2f1423af 100644 --- a/.gitbook/4-validators/3-join-mainnet-testnet.md +++ b/.gitbook/4-validators/3-join-mainnet-testnet.md @@ -117,7 +117,7 @@ Your node can rapidly sync with the network using state sync without replaying h To set state sync enabled, RPC servers and trusted block info (height and hash) are required. -You can use the following public RPC endpoints provided by Medibloc team. +You can use the following public RPC endpoints provided by MediBloc team. - 3.35.82.40:26657 - 13.124.96.254:26657 - 52.79.108.35:26657 diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md b/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md index e69de29b..d67635cf 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md @@ -0,0 +1,111 @@ +# Oracle Registration + +This document is an instruction to register an oracle to Panacea + +## Get Trusted Block Information + +To request oracle registration to Panacea, trusted block information (height and hash), which will be used for [light client](), is required and need to be verified by other registered oracle. + +You can get trusted block information by: +```bash +BLOCK=$(panacead q block --node ) + +HEIGHT=$(echo $BLOCK | jq -r .block.header.height) +HASH=$(echo $BLOCK | jq -r .block_id.hash) +``` + +If you need more information about public RPC endpoints provided by MediBloc team, you can refer [this](https://github.com/medibloc/panacea-mainnet#public-endpoints) + +## Request to Register Oracle + +In addition to the trusted block information, the following arguments are also required in oracle registration. + +| Argument | requirement | Description | +|-----------------------------------|-------------|------------------------------------------------------------------------------------------------------| +| oracle-commission-rate | required | The desired initial oracle commission rate | +| oracle-commission-max-rate | required | The maximum oracle commission rate. The oracle commission rate cannot be greater than this max rate. | +| oracle-commission-max-change-rate | required | The maximum rate that an oracle can change once. It will be reset 24 hours after the last change. | +| oracle-endpoint | optional | The endpoint of oracle to be used | + +With the above arguments, you can now request to register your oracle to Panacea. + +```bash +docker run \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v /oracle:/oracle \ + ghcr.io/medibloc/panacea-oracle:latest \ + ego run /usr/bin/oracled register-oracle \ + --trusted-block-height ${HEIGHT} \ + --trusted-block-hash ${HASH} \ + --oracle-commission-rate 0.1 \ + --oracle-commission-max-rate 0.3 \ + --oracle-commission-max-change-rate 0.01 \ + --oracle-endpoint "" +``` + +Then, a new key pair, called `Node Key`, and its remote report will be generated. +The `Node Key` is used to be shared the oracle private key. +Since the oracle private key must be shared in a very secure way, the key will be encrypted with the public key of the `Node Key` so that only the oracle can decrypt it. + +{% hint style="danger" %} +The private key of `Node Key` is also stored in secure way as a sealed file, named `node_priv_key.sealed` in default. +This `node_priv_key.sealed` file is the only clue to decrypt the encrypted oracle private key, we recommend to manage it very carefully in case that you need to restore the oracle private key again later. +{% endhint %} + +If you have tried to request `register-oracle` before, previously generated `node_priv_key.sealed` would exist. +And the app will ask, + +``` +There is an existing node key. +Are you sure to delete and re-generate node key? +``` + +If you're sure to re-generate the `Node Key` and re-request oracle registration, please enter `y`. +Or, we recommend to back up the existing `node_priv_key.sealed` file. + +## Subscribe Approval of Registration + +If the transaction for request of oracle registration succeeds, oracle will start to subscribe `ApproveOracleRegistrationEvent`. +Other oracles already registered will do some verifications of this registration by checking if: +- correct version of oracle binary is used +- the oracle is running inside an enclave +- the `Node Key` is generated inside the enclave +- the trusted block information is valid + +When the registration is verified successfully, other oracles will send a transaction for approval of the oracle registration. +The oracle would detect the approval, and then the oracle start to retrieve the oracle private key. +As a result of retrieval of oracle private key, a sealed file named `oracle_priv_key.sealed` (default file name) will be generated. +Using the sealed oracle private key, this oracle is now ready to perform tasks such as verifying data or other oracles. +For more information about what oracle does, please refer the [running an oracle node](5-running-node#what-oracle-does.md). + +{% hint style="danger" %} +Like `node_priv_key.sealed`, `oracle_priv_key.sealed` is also very important for working as a valid oracle. +Thus, we highly recommend to manage the `oracle_priv_key.sealed` file very carefully. +In case that operator lost the `oracle_priv_key.sealed` file for any reason, it can be retrieved again using `get-oracle-key` CLI with the `node_priv_key.sealed` file, which is generated when request oracle registration above. +{% endhint %} + +## Manually Retrieve Oracle Private Key + +For any reasons, the oracle can stop before the oracle private key is retrieved. +In this case, you can also retrieve the oracle private key through `get-oracle-key` CLI. +If at least one registered oracle approves the registration, this will be able to retrieve the oracle private key successfully. + +```bash +docker run \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v ${ANY_DIR_ON_HOST}:/oracle \ + ghcr.io/medibloc/panacea-oracle:latest \ + ego run /usr/bin/oracled get-oracle-key +``` + +You can check the status of your registration with the uniqueID and oracle address. + +```bash +panacead q oracle oracle-registration +``` + +If at least one oracle approved this registration, the `encrypted_oracle_priv_key` will have some value. + +Now, you are ready to run your own oracle. Please refer the [running a node](./5-running-node.md) instructions. \ No newline at end of file From bab1547dd6ad7e192611779e80d44a4a81402499 Mon Sep 17 00:00:00 2001 From: Hansol Lee <38912532+H4NLee@users.noreply.github.com> Date: Thu, 12 Jan 2023 18:21:26 +0900 Subject: [PATCH 49/84] docs: update oracle info (#616) --- .../6-update-oracle-info.md | 34 +++++++++++++++++++ ...-upgrading-node.md => 7-upgrading-node.md} | 0 .gitbook/SUMMARY.md | 3 +- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md rename .gitbook/5-oracles/1-operate-oracle-nodes/{6-upgrading-node.md => 7-upgrading-node.md} (100%) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md b/.gitbook/5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md new file mode 100644 index 00000000..ad49a14f --- /dev/null +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md @@ -0,0 +1,34 @@ +# Update Oracle Information + +This document outlines how to edit the oracle information (endpoint and commission rate) + +## Command Line for Updating + +Using the below CLI, you can update your endpoint and/or commission rate + +```bash +docker run \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v /oracle:/oracle \ + ghcr.io/medibloc/panacea-oracle:latest \ + ego run /usr/bin/oracled update-oracle-info \ + --oracle-endpoint "" \ + --oracle-commission-rate +``` + +| Flag | requirement | Description | +|-----------------------------------|-------------|-----------------------------| +| endpoint | optional | The endpoint of oracle | +| oracle-commission-rate | optional | The oracle commission rate. | + +As you can see above table, both flags are optional. +You can enter the flags you want to change. +It is noted that the oracle commission rate cannot be greater than oracle max change rate. +And once changed, the oracle commission rate cannot be changed within the next 24 hours. + +You can confirm the changes you made if the transaction succeeds + +```bash +panacead q oracle oracle +``` \ No newline at end of file diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/6-upgrading-node.md b/.gitbook/5-oracles/1-operate-oracle-nodes/7-upgrading-node.md similarity index 100% rename from .gitbook/5-oracles/1-operate-oracle-nodes/6-upgrading-node.md rename to .gitbook/5-oracles/1-operate-oracle-nodes/7-upgrading-node.md diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index b9e98813..8f5adccb 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -69,5 +69,6 @@ * [Genesis Oracle](5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md) * [Oracle Registration](5-oracles/1-operate-oracle-nodes/4-oracle-registration.md) * [Running a Node](5-oracles/1-operate-oracle-nodes/5-running-node.md) - * [Upgrading a Node](5-oracles/1-operate-oracle-nodes/6-upgrading-node.md) + * [Updating Oracle Information](5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md) + * [Upgrading a Node](5-oracles/1-operate-oracle-nodes/7-upgrading-node.md) * FAQ \ No newline at end of file From 612606f48f5e66d9928d1c4af4bc3c75e6f7887d Mon Sep 17 00:00:00 2001 From: gyuguen Date: Thu, 12 Jan 2023 18:55:25 +0900 Subject: [PATCH 50/84] docs: add a genesis oracle registration docs (#613) --- .../3-genesis-oracle.md | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md b/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md index e69de29b..d29d21a7 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md @@ -0,0 +1,216 @@ +# Genesis Oracle + +- Status: Draft +- Created: 2023-01-11 +- Modified: 2023-01-11 +- Authors + - Gyuguen Jang + - Youngjoon Lee + - Hansol Lee + - Myongsik Gong + - Inchul Song + + +## Synopsis +This document describes how to register a genesis oracle with Panacea. + +In order for DEP to operate properly, one or more trusted oracles must be registered in Panacea. +In general, the genesis oracle will already be registered on the testnet or mainnet. +This guide is useful for testing on the localnet. + +## Genesis Oracle Registration +To register a genesis oracle, you must first complete the [oracle-initialization](./2-oracle-initialization.md) step. +Panancea needs to complete the steps before executing `panacead start` in [deploy-localnet](../../4-validators/2-deploy-localnet.md). +You must first register the genesis oracle in `genesis.json` of Panacea + +### UniqueID +UniqueID can be extracted from Oracle's binary. +Execute the command in oracle as follows: +```shell +docker run \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + ghcr.io/medibloc/panacea-oracle:latest \ + ego uniqueid /usr/bin/oracled +``` +**Output** +``` +EGo v1.0.1 (e1e48c9dbfdfd3cb2f2fda7602729162c9f762cc) + +``` + +### Genesis Oracle Registration in Panacea + +After uniqueID extraction is completed, the genesis oracle must be registered in `genesis.json` of Panacea. + +We provide a CLI for this process. +``` +panacead add-genesis-oracle \ + --oracle-unique-id + --oracle-account \ + --oracle-commission-rate \ + --oracle-commission-max-rate \ + --oracle-commission-max-change-rate \ + --oracle-endpoint {oracle_endpoint} +``` + +| Argument | Requirement | Description | +|-----------------------------------|-------------|------------------------------------------------------------------------------------------------------| +| oracle-unique-id | optional | The uniqueID to be set in the params of the oracle module and the genesis oracle | +| oracle-account | optional | The address or key name of the account to be registered as an genesis oracle | +| oracle-commission-rate | optional | The desired initial oracle commission rate | +| oracle-commission-max-rate | optional | The maximum oracle commission rate. The oracle commission rate cannot be greater than this max rate. | +| oracle-commission-max-change-rate | optional | The maximum rate that an oracle can change once. It will be reset 24 hours after the last change. | +| oracle-endpoint | optional | The endpoint of oracle to be used | + +You can check the oracle registered in `genesis.json` +``` +cat $HOME/.panacea/config/genesis.json | jq .app_state.oracle.oracles +``` +**Output** +```json +[ + { + "oracle_address": "", + "unique_id": "", + "endpoint": "", + "update_time": "", + "oracle_commission_rate": "", + "oracle_commission_max_rate": "", + "oracle_commission_max_change_rate": "" + } +] +``` + +### Start block generation in Panacea +You need to launch the Panacea to start generating blocks. +```shell +panacead start +``` + +## Oracle Key Pair and Remote Report + +The genesis oracle must create an oracle private key and public key to use for data encryption/decryption. +The oracle also issues a remote report to allow others to prove that the genesis oracle is running inside secure enclave and the oracle key pair is generated inside the enclave. + +### Generates oracle key pair and remote report in oracle +The genesis oracle needs to generate an oracle key pair and a remote report. +However, before generating oracle keys and remote reports, you need to know trusted block information from Panacea. + +In fact, the genesis oracle does not need trusted block information for this process. +The reason is that oracle key pair and remote report generation process do not retrieve data from Panacea. +However, when the oracle participates in the verification operation (`oracled start`), the oracle needs to use a light client as it will retrieve data from Panacea. +Therefore, unless trusted block information is received during the process of generating an oracle key, the genesis oracle has no way to retrieve this block information. + +You can get trusted block information by: +```shell +BLOCK=$(panacead q block --node ) + +HEIGHT=$(echo $BLOCK | jq -r .block.header.height) +HASH=$(echo $BLOCK | jq -r .block_id.hash) +``` + +After getting the height and hash of the block, you can generate the necessary keys and remote report via the CLI below. +``` +docker run \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v :/oracle \ + ghcr.io/medibloc/panacea-oracle:latest \ + ego run /usr/bin/oracled gen-oracle-key \ + --trusted-block-height $HEIGHT \ + --trusted-block-hash $HASH + +``` + +| Argument | Requirement | Description | +|----------------------|-------------|-------------------------------------------------------------| +| trusted-block-height | required | Trusted block height of Panacea | +| trusted-block-hash | required | Block hash corresponding to trusted block height of Panacea | + + +When the oracle key and remote report are generated successfully, they are stored as file with the below structure: + +``` +# Oracle home +. +├── config.toml +├── data +│   └── light-client.db +│   ├── 000001.log +│   ├── CURRENT +│   ├── LOCK +│   ├── LOG +│   └── MANIFEST-000000 +├── oracle_priv_key.sealed +└── oracle_pub_key.json +``` +- `data/light-client.db`: Repository of Light client. +- `oracle_priv_key.sealed`: Oracle private key sealed file. +- `oracle_pub_key.json`: A json file containing oracle's public key and remote report. + +**oracle_pub_key.json** +```json +{ + "public_key_base64": "", + "remote_report_base64": "" +} +``` + +### Submit a parameter change proposal +The generated oracle public key and its remote report should be set by governance, a proposal for changing module parameter of oracle module. + +```shell +panacead tx gov submit-proposal param-change proposal.json \ + --from \ + --chain-id \ + --gas auto \ + --gas-adjustment 1.3 \ + --gas-prices 5umed \ + -y +``` +**proposal.json** +```json +{ + "title": "", + "description": "<description>", + "changes": [ + { + "subspace": "oracle", + "key": "OraclePublicKey", + "value": "<oracle-pub-key-base64>" + }, + { + "subspace": "oracle", + "key": "OraclePubKeyRemoteReport", + "value": "<oracle-remote-report-base64>" + } + ], + "deposit": "100000000000umed" +} +``` + +After submitting the proposal, vote on the proposal and wait for it to pass. +```shell +panacead tx gov vote {proposal_id} yes \ + --from <key> \ + --chain-id <chain_id> \ + --fees 1000000umed \ + -y +``` + +If the proposal passes, you can check the changes with the following CLI. +```shell +panacead q oracle params +``` +**Output** +```shell +params: + oracle_pub_key_remote_report: "<oracle-remote-report-base64>" + oracle_public_key: "<oracle-public-key-base64>" + unique_id: "<unique-id>" +``` + +When all these processes are completed, the genesis oracle can operate normally. + +Next, see [Running node](./5-running-node.md) where you can run the genesis oracle. \ No newline at end of file From d70675d999513017bd71635f6db281420a9b3e41 Mon Sep 17 00:00:00 2001 From: InChul <49394875+inchori@users.noreply.github.com> Date: Fri, 13 Jan 2023 10:06:15 +0900 Subject: [PATCH 51/84] docs: add oracle initialization docs (#611) --- .../2-oracle-intialization.md | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md b/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md index e69de29b..dc248739 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md @@ -0,0 +1,129 @@ +# Oracle Initialization + +#### Before run the oracle, you should initialize the oracle configuration. + +## Preparations + +Before initializing the oracle, you should install the oracle described +in [oracle-installation](./1-oracle-installation.md). +After install the oracle, create an empty directory on your host, to be mounted as the `/home_mnt` directory in the +enclave. + +```bash +mkdir <directory-you-want>/oracle +``` + +```bash +export ORACLE_CMD="docker run --rm \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v <directory-you-want>/oracle:/oracle ghcr.io/medibloc/panacea-oracle:latest \ + ego run /usr/bin/oracled" +``` + +## Command Line of Initialization + +```bash +$ORACLE_CMD init --home /home_mnt/.oracle +``` + +When run the above CLI for initializing the oracle, the `config.toml` file will be generated under +the `<directory-you-want>/.oracle` in the enclave. +The default `config.toml` file will be shown like this: + +```toml +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml +# Write comment later +############################################################################### +### Base Configuration ### +############################################################################### + +log-level = "info" +oracle-mnemonic = "" +oracle-acc-num = "0" +oracle-acc-index = "0" +data-dir = "data" + +oracle-priv-key-file = "oracle_priv_key.sealed" +oracle-pub-key-file = "oracle_pub_key.json" +node-priv-key-file = "node_priv_key.sealed" + +############################################################################### +### Panacea Configuration ### +############################################################################### + +[panacea] + +chain-id = "" +grpc-addr = "http://127.0.0.1:9090" +rpc-addr = "tcp://127.0.0.1:26657" +default-gas-limit = "400000" +default-fee-amount = "2000000umed" + +# A primary RPC address for light client verification + +light-client-primary-addr = "tcp://127.0.0.1:26657" + +# Witness addresses (comma-separated) for light client verification + +light-client-witness-addrs = "tcp://127.0.0.1:26657" + +# Setting log information for light client + +light-client-log-level = "error" + +############################################################################### +### IPFS Configuration ### +############################################################################### + +[ipfs] + +ipfs-node-addr = "127.0.0.1:5001" + +############################################################################### +### API Configuration ### +############################################################################### + +[api] + +listen-addr = "127.0.0.1:8080" +write-timeout = "60" +read-timeout = "15" +``` + +## Configuring Some Default Setting + +#### Base Configuration + +In `Base Configuration`, you need to configure a `oracle-mnemonic`, `oracle-acc-num`, and `oracle-acc-index`. Those +components should be corresponded to account that you registered in the Panacea. + +#### Panacea Configuration + +In `Panacea Configuration`, you need to configure a chain ID of Panacea. If you want to join the oracle to Panacea +mainnet or testnet, please check the chain IDs +in [mainnet-repoistory](https://github.com/medibloc/panacea-mainnet#intro) +or [testnet-repository](https://github.com/medibloc/panacea-testnet#intro), respectively. + +The default `grpc-addr` and `rpc-addr` setting is based on localnet. So if you want to connect with the Panacea +mainnet, the `grpc-addr` will be `https://grpc.gopanacea.org` and the `rpc-addr` will be `https://rpc.gopanacea.org`. +Also, the `light-client-primary-addr` and `light-client-witness-addrs` are as same as `rpc-addr`, if you want to +connect with the Panacea mainnet. + +The `default-gas-limit` and `default-fee-amount` are set as `400000` and `2000000umed`, since the remote report has a +large bytes for oracle registration and oracle upgrade. So if you have finished an oracle registration or upgrade, you +could set a lower gas limit and fee amount than default setting. + +#### IPFS Configuration + +The oracle will use a public IPFS node for now. If you want to run a local IPFS node, the `ipfs-node-addr` is as same as +default setting. Also, you need to check that the IPFS gateway and the oracle `listen-addr` are at same port. You can +change the IPFS gateway in `$HOME/.ipfs/config`. If you want to know about RPC API of the IPFS, please refer +the [IPFS documentation](https://docs.ipfs.tech/reference/kubo/rpc/). + +## Next + +If you have done the oracle initialization, you could register oracle based on above configuration. If you want to know +how to register oracle, please refer the [oracle-registration](./4-oracle-registration.md) documentation. + From f09c838491ee08190b4307047cdf9544b940de9e Mon Sep 17 00:00:00 2001 From: Youngjoon Lee <yjlee@medibloc.org> Date: Fri, 13 Jan 2023 10:37:46 +0900 Subject: [PATCH 52/84] docs: add DEP user flow spec (#597) Co-authored-by: audtlr24 <audtlr24@gmail.com> --- .../1-dep-specs/1-user-flow.md | 65 +++++++++++++++--- .../1-dep-specs/images/user-flow.drawio.png | Bin 0 -> 53524 bytes .../1-dep-specs/images/user-flow.drawio.xml | 2 + 3 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 .gitbook/3-protocol-devs/1-dep-specs/images/user-flow.drawio.png create mode 100644 .gitbook/3-protocol-devs/1-dep-specs/images/user-flow.drawio.xml diff --git a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md index 60171b94..17d14e9c 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md @@ -1,8 +1,8 @@ # User Flow - Status: Draft -- Created: 2022-12-23 -- Modified: 2022-12-23 +- Created: 2023-01-11 +- Modified: 2023-01-11 - Authors - Youngjoon Lee <yjlee@medibloc.org> - Gyuguen Jang <gyuguen.jang@medibloc.org> @@ -13,23 +13,68 @@ ## Synopsis -TODO: Blah blah... +This document specified the entire user flow in the Data Exchange Protocol (hereafter 'DEP'). +This document defines the key players essential to operate the DEP, and describes how the players interact to complete the whole data exchange process. + +It is recommended to walk through this document first before diving deeply into detailed specifications. ### Motivation -TODO: Blah blah... +DEP aims to establish a reliable communication layer between two parties who do not have strong trust in each other in decentralized environments. +To achieve this goal without centralized/authorized mediators, DEP introduces four key players: data consumer, provider, oracle, and chain validator. These key players collaborate to verify all aspects of the data exchange to minimize security/privacy vulnerabilities. ### Definitions -- `Data Provider`: TODO -- TODO +#### Key Players + +##### Data Consumer +A data consumer is an individual or an organization who wants to consume certain kinds of data for specific purposes, with or without paying. + +##### Data Provider +A data provider is an individual or an organization that holds data and the permission to provide data to data consumers to obtain benefits, such as incentives or services. + +##### Oracle (Oracle operator) +An oracle is a data validator that guarantees data validity and integrity while data is delivered from data providers to data consumers. +Data verification is essential to ensure the atomicity of data delivery and incentive payments. + +##### Panacea Blockchain Validator +A Panacea blockchain validator is a blockchain node operator that participates in the blockchain consensus process to guarantee the integrity of the whole process of DEP, which includes consuming data, providing data, validating data, and executing payments. ## Technical Specification -### User Flow +![](images/user-flow.drawio.png) + +The diagram describes each key player interacts with each other to complete a cycle of data exchange. The whole process consists of several steps below. + +### Data Deal Registration + +A data consumer creates a data deal, specifying data schema, a budget in MED, the maximum number of data to consume, and agreement terms. The data consumer should publish the data deal to a public and secure environment, such as a public blockchain, to ensure that the data deal is not changed by anyone else after it is created. In this document, the Panacea blockchain is used for that public environment. For more details of the data deal, please see the [Data Deal](2-data-deal.md) specification. + +### Data Validation + +A data provider willing to provide data that meet the requirements desired by a data consumer should request a data validation to one of the verified oracles in the network. +The oracle validates the validity and integrity of data based on the requirements specified by the data consumer in the data deal. As a result of the data validation, the oracle issues a data validation certificate with a cryptographic signature. Also, the oracle uploads the data to the storage accessible by the data consumer. +The data is encrypted securely for each communication. For more details on the data validation and encryption, please see the [Data Validation](4-data-validation.md) and the [Confidential Oracle](5-confidential-oracle.md) specifications. + +### Consent Submission + +The data provider submits a consent of data provision, including the data validation certificate issued by the oracle. +The Panacea blockchain, operated by validators, validates the conformance and integrity of the consent and the data validation certificate. +For more details on the consent and the data validation, please see the [Data Provider Consent](3-data-provider-consent.md) and [Data Validation](4-data-validation.md) specifications. + +### Incentive Distribution + +As soon as the consent is accepted by the Panacea blockchain, the proper amount of MED coins are automatically distributed to the data provider and the oracle that issued the data validation certificate. +It is safe to distribute incentives right after the consent submission is accepted because the data consumer can immediately access the provided data. +The amount of incentives for each data provision is calculated by the total budget and the maximum number of data to consume specified by the data consumer in the data deal. The distribution ratio between the data provider and the oracle is determined by the commission rate promised by the oracle in the Panacea blockchain. +For more details, please see the [Incentives](6-incentives.md) specification. + +### Data Delivery + +As a result of the [Data Validation](#data-validation) and [Consent Submission](#consent-submission), the encrypted data is uploaded to the storage, and the data consumer can obtain the unique identifier of the data stored in the storage from the Panacea blockchain. Using the unique identifier, the data consumer fetches the encrypted data from the storage. +To decrypt the data, the data consumer requests a secret key to the oracle that validated the data and issued the validation certificate contained in the submitted consent. -TODO: blahblah with diagrams (e.g. seq diagrams) ## Backwards Compatibility @@ -38,7 +83,7 @@ Not applicable. ## Forwards Compatibility -TODO: blahblah +To be described. ## Example Implementations @@ -50,7 +95,7 @@ None at present. ## History -- 2022-12-23: Initial draft finished +- 2023-01-11: Initial draft finished ## Copyright diff --git a/.gitbook/3-protocol-devs/1-dep-specs/images/user-flow.drawio.png b/.gitbook/3-protocol-devs/1-dep-specs/images/user-flow.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..709306f068adc2bf3676264d93196c91b5378a7d GIT binary patch literal 53524 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 literal 0 HcmV?d00001 diff --git a/.gitbook/3-protocol-devs/1-dep-specs/images/user-flow.drawio.xml b/.gitbook/3-protocol-devs/1-dep-specs/images/user-flow.drawio.xml new file mode 100644 index 00000000..ce2aa1da --- /dev/null +++ b/.gitbook/3-protocol-devs/1-dep-specs/images/user-flow.drawio.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mxfile host="app.diagrams.net" modified="2023-01-11T05:40:05.095Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" version="20.7.4" etag="OmEN4H1yehcedVwhfQWn" type="google"><diagram id="eqNNXCOJZti-axIanlw2">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</diagram></mxfile> \ No newline at end of file From 97788f57658e5623a41246068ec0733f17c5b238 Mon Sep 17 00:00:00 2001 From: audtlr24 <audtlr24@gmail.com> Date: Fri, 13 Jan 2023 11:45:12 +0900 Subject: [PATCH 53/84] docs: running oracle node (#617) --- .../1-operate-oracle-nodes/5-running-node.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md b/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md index e69de29b..080b13dc 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md @@ -0,0 +1,88 @@ +# Running a Node + +## Overview + +If you have completed the previous steps, now is the step to actually run oracle. + +The oracle is responsible for validating the provider's data and ensuring that the data is transmitted securely using the `oracle key`. +In this process, oracle operators can earn commissions according to the commission rate registered to Panacea. +The oracle also serves to validate and approve `registration/upgrade` requests from other oracles. + +You can see the details in [What oracle does](#what-oracle-does). + +## Prerequisites +- [Hardware Requirement](5-oracles/1-operate-oracle-nodes/1-oracle-installation.md) +- Complete [Oracle Registration](5-oracles/1-operate-oracle-nodes/4-oracle-registration.md) or [Genesis Oracle](5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md) + - Your oracle have to be registered in Panacea + - The `oracle_priv_key.sealed` must be in the oracle home path + +## Start oracle + +You can start oracle with following CLI: +```bash +docker run \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v ${ANY_DIR_ON_HOST}:/oracle \ + ghcr.io/medibloc/panacea-oracle:latest \ + ego run /usr/bin/oracled start +``` +If oracle start is successful, you can see the following log message like example below: +``` +EGo v1.1.0 (4625a610928f4f4b1ea49262c363376b1e574b6c) +[erthost] loading enclave ... +[erthost] entering enclave ... +[ego] starting application ... +time="2023-01-11T07:40:31Z" level=info msg="successfully connect to IPFS node" +time="2023-01-11T07:40:31Z" level=info msg="dialing to Panacea gRPC endpoint: http://127.0.0.1:9090" +time="2023-01-11T07:40:31Z" level=info msg="Panacea event subscriber is started" +time="2023-01-11T07:40:31Z" level=info msg="subscribe RegisterOracleEvent. query: message.action = 'RegisterOracle'" +time="2023-01-11T07:40:31Z" level=info msg="subscribe UpgradeOracleEvent. query: message.action = 'UpgradeOracle'" +time="2023-01-11T07:40:31Z" level=info msg="HTTP server is started: 127.0.0.1:8081" +``` + +## What oracle does + +### Validate provider data & issue certificate + +Oracle provides a REST API to validate data from a provider and issue a certificate. + +Validation procedure is as follows: +1. Check the address of the requested provider with JWT +2. Check the status of related `deal` +3. Decrypt provider's encrypted data & check data hash and data schema + +If validation passes successfully, oracle issues a certificate as follows: +1. Generate a `secret key` by combining `oracle private key`, deal ID, and data hash +2. Re-encrypt the data using the `secret key` and put it in `IPFS` +3. Issue a certificate with `oracle private key` signature + +Providers will be able to submit consent to Panacea with the issued certificate. +Panacea ensures that a commission is paid to the oracle operator who issued the certificate when the data delivery is successfully completed. + +### Safely transmit provider data accessibility to consumer + +Oracle provides a REST API to get data accessibility to consumer. + +After the `submit-consent` transaction succeeds in Panacea, oracle transmits secret key that enables data access to the consumer. +The detailed process is as follows: +1. Check the address of the requested consumer with JWT +2. Check if the requested consumer is the owner of the `deal` +3. Check if the `submit-consent` transaction succeeds +4. Make `encrypted secret key` using `consumer public key` +5. Response with `encrypted secret key` to consumer + +Consumer can obtain the `secret key` through his/her `private key`, and can decrypt data from `IPFS`. + +### Validate and approve registration/upgrade requests of other oracles + +Oracle subscribes `registration/upgrade` events from Panacea. + +When another oracle sends a `registration/upgrade`, the running oracle do some verifications by checking if: +- correct version of oracle binary is used +- the oracle is running inside an enclave +- the `Node Key` is generated inside the enclave +- the trusted block information is valid +- the oracle is registered (at upgrade requests) + +When the `registration/upgrade` is verified successfully, oracle send a transaction for approval of the oracle `registration/upgrade`. \ No newline at end of file From 93625649720f6b96d573f5725bd756beb49801ef Mon Sep 17 00:00:00 2001 From: Hansol Lee <38912532+H4NLee@users.noreply.github.com> Date: Fri, 13 Jan 2023 12:20:41 +0900 Subject: [PATCH 54/84] docs: oracle upgrade for oracle operators (#619) --- .../7-oracle-upgrade.md | 112 ++++++++++++++++++ .gitbook/SUMMARY.md | 2 +- 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md b/.gitbook/5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md new file mode 100644 index 00000000..20c9be09 --- /dev/null +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md @@ -0,0 +1,112 @@ +# Oracle Upgrade + +This document is about the whole process of oracle upgrade. + +## Oracle Upgrade Process + +All oracles registered in Panacea are forced to run oracle with the same unique ID stored in the oracle module. +Since the new version (to be upgraded) of oracle will have a unique ID different from the existing one, the new unique ID should be registered in Panacea. +This process is determined by on-chain governance, thus upgrade can be proposed by an `oracle-upgrade` proposal. + +### Submit Proposal for Oracle Upgrade + +Oracle upgrade can be proposed by submitting an `oracle-upgrade` proposal as shown below: + +```bash +panacead tx gov submit-proposal oracle-upgrade \ + --title "<proposal-title>" \ + --description "<proposal-description>" \ + --upgrade-height <upgrade-target-height> \ + --upgrade-unique-id "<oracle-unique-id>" \ + --deposit "<deposit-in-umed>" \ + --from "<proposer-key-name>" \ + --chain-id "<chain-id>" \ + --fees "1000000umed" +``` + +- title: The title of oracle upgrade proposal +- description: The description of oracle upgrade proposal +- upgrade-height: Target height to be upgraded +- upgrade-unique-id: Unique ID of oracle to be upgraded +- deposit: A deposit for proposal + +If the proposal passes, you can check the oracle upgrade information with the below CLI. + +```bash +panacead q oracle oracle-upgrade-info +``` + +### Upgrade Oracle Node + +{% hint style="info" %} +You can upgrade oracle any time after an `oracle-upgrade` proposal has passed (even before the upgrade target height is reached). +However, since the new version of oracle can be active after the target height, the current version of oracle must be run before the target height. + +You do not have to stop the old version of oracle when upgrading to a new version of oracle. +You can run different versions of oracle at the same time using the `home` flag. +{% endhint %} + +#### Initialization + +The `oracle_priv_key.sealed` used in the previous version cannot be used in the new version of oracle. +(Because it cannot be decrypted in the new version of oracle. For more info, refer to [this](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md)) +Therefore, the new version of oracle should also be shared the oracle private key. +This is very similar to the process of registering oracle. +Let's start with [initialization](2-oracle-intialization.md) of the new version of oracle. + +```bash +export ORACLE_CMD="docker run --rm \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v <directory-you-want>/oracle:/oracle ghcr.io/medibloc/panacea-oracle:latest \ + ego run /usr/bin/oracled" + + $ORACLE_CMD init --home /home_mnt/.oracle-new +``` + +You can rename the path where you want to store the configuration file of the new version of oracle. +For this document, we will use `.oracle-new`. +After initialization, complete the configuration by referring to the [Configuring Some Default Setting](2-oracle-intialization#configuring-some-default-setting.md). + +#### Request to Upgrade Oracle + +The purpose of this request is to securely be shared the oracle private key for a new version of oracle. +It is similar to sharing the oracle private key in [oracle registration](4-oracle-registration#request-to-register-oracle.md). +Prior to the request, trusted block information is also required. +You can get trusted block information with the following command: + +```bash +BLOCK=$(panacead q block --node <node-rpc-address>) + +HEIGHT=$(echo $BLOCK | jq -r .block.header.height) +HASH=$(echo $BLOCK | jq -r .block_id.hash) +``` + +Then, request an upgrade using this trusted block information. + +```bash +$ORACLE_CMD upgrade-oracle \ + --trusted-block-height ${HEIGHT} \ + --trusted-block-hash ${HASH} + --home /home_mnt/.oracle-new +``` + +Like oracle registration, a `Node Key` to be used for sharing the oracle private key will be generated and stored. +You will find that the `node_priv_key.sealed` file is stored in `<directory-you-want>/oracle/.oracle-new`. +This `node_priv_key.sealed` file is also necessary to retrieve the oracle private key, so it is highly recommended to manage it safely. + +#### Subscribe Approval of Upgrade + +If the transaction for `upgrade-oracle` succeeds, oracle will start subscribing to the `ApproveOracleUpgradeEvent`. +Upon approval by other oracles, this new version of oracle can be shared the oracle private key. +This process is similar to [oracle-registration](4-oracle-registration#subscribe-approval-of-registration.md), so please refer it for details. + +#### Running the Upgraded Oracle + +After reaching the target height of the upgrade, you can start the new version of oracle. + +```bash +$ORACLE_CMD start --home /home_mnt/.oracle-new +``` + +See [running-oracle](5-running-node.md) for more information. \ No newline at end of file diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index 8f5adccb..a3543bf8 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -70,5 +70,5 @@ * [Oracle Registration](5-oracles/1-operate-oracle-nodes/4-oracle-registration.md) * [Running a Node](5-oracles/1-operate-oracle-nodes/5-running-node.md) * [Updating Oracle Information](5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md) - * [Upgrading a Node](5-oracles/1-operate-oracle-nodes/7-upgrading-node.md) + * [Oracle Upgrade](5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md) * FAQ \ No newline at end of file From 074efbf20cb9c1aa8ea60c28b8db92067df7b392 Mon Sep 17 00:00:00 2001 From: InChul <49394875+inchori@users.noreply.github.com> Date: Fri, 13 Jan 2023 14:00:46 +0900 Subject: [PATCH 55/84] docs: add confidential oracle docs (#599) --- .../1-dep-specs/5-confidential-oracle.md | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md b/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md index e69de29b..ed1eaef2 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md @@ -0,0 +1,70 @@ +# Confidential Oracle + +- Status: Draft +- Created: 2023-01-06 +- Modified: 2023-01-06 +- Authors + - Inchul Song <icsong@medibloc.org> + - Youngjoon Lee <yjlee@medibloc.org> + - Gyuguen Jang <gyuguen.jang@medibloc.org> + - Hansol Lee <hansol@medibloc.org> + - Myongsik Gong <myongsik_gong@medibloc.org> + +## Synopsis + +This document explains that why the oracles must use confidential computing. + +## Motivation + +In DEP, the data must be verified as explained in the [data validation documentation](./4-data-validation.md). +Verifying data means that the content of data could be shown to the oracle. However, no one would want their data to be +exposed to the oracle for data verification. There may also be malicious oracles to exploit the data unfairly. To +prevent it, we have designed the DEP oracle with confidential computing. Confidential computing guarantees that only +selected code (binary) can access data in the secure enclave. Also, it could protect a sensitive data from being leaked +by malicious operators while verifying a data correctly in decentralized system. + +## Confidential Oracle + +The oracle operators(human) can see the content of sensitive data. For example, if the oracle software stores the +important sensitive data to the disk or storage without sealing it, it can be read by anyone who can access the disk or +storage. So we developed the confidential oracle for preventing the case from the malicious oracle by using below +sections. + +### Technical Specification + +For running the DEP oracle with confidential computing, we choose an Intel SGX which offers hardware-based memory +encryption for data security +using [Microsoft Azure Confidential Computing VM](https://learn.microsoft.com/en-us/azure/confidential-computing/overview). +Also, we choose an [EGo](https://www.edgeless.systems/products/ego/) SDK which enables to develop confidential apps +written in Go language. + +### Oracle Key + +An oracle key is an asymmetric key that should be shared across all oracles. The request from provider and consumer that +oracle receive must be encrypted by the oracle public key. If the secure data encryption and decryption need to be +performed, the corresponding oracle private must be held by every oracle securely. How the all oracle shared the oracle +private key and how they stored the key securely will be described in next section. + +### Oracle Key Handshake + +The oracle private key is sealed by unique ID which is for the Intel SGX enclaves. If the oracle operator modified the +source code of the oracle, the unique ID will be changed. If the malicious oracle operator modified the source code of +the oracle to print logs of sensitive data or to leak a contents somewhere else, it would cause the serious privacy +problems. It means that the all oracle operators must use the only genuine binary built by selected code. +The only genuine binary can unseal the data in the SGX secure enclave. + +If the oracle wants to register, it must use remote report composed of the promised security version and unique ID. +So the one of the oracle approves the registration if the new oracle's remote report is valid. +If you want a register the oracle, you can verify remote report that is valid or not using +[CLI](../../5-oracles/7-verfiy-remote-report.md). After the oracle registration passed, the new oracle can retrieve the shared oracle +private key. + +### Sealing Secrets and States + +All secrets and important information, such as the shared oracle private key and the state of blockchain light client, +must be sealed before it is stored to the disk, so that anyone outside the enclave cannot read it. The sealing must be +done with the unique ID of the enclave, so that any modified enclave cannot unseal secrets. + +So how to we set a correct unique ID and how to know it is not malicious binary? The correct unique ID will be +determined by Panacea governance. We can know the correct unique ID from Panacea as Single Source of Truth(SSOT), +and know that what the correct genuine binary is. From 140f72113dcc3dc3cdc063dc1c1ac5f905b5ae8f Mon Sep 17 00:00:00 2001 From: gyuguen <gyuguen.jang@medibloc.org> Date: Fri, 13 Jan 2023 15:45:20 +0900 Subject: [PATCH 56/84] docs: add verify remote report (#620) --- .../7-upgrading-node.md | 0 .../8-verify-remote-report.md | 95 +++++++++++++++++++ .gitbook/SUMMARY.md | 2 +- 3 files changed, 96 insertions(+), 1 deletion(-) delete mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/7-upgrading-node.md create mode 100644 .gitbook/5-oracles/1-operate-oracle-nodes/8-verify-remote-report.md diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/7-upgrading-node.md b/.gitbook/5-oracles/1-operate-oracle-nodes/7-upgrading-node.md deleted file mode 100644 index e69de29b..00000000 diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/8-verify-remote-report.md b/.gitbook/5-oracles/1-operate-oracle-nodes/8-verify-remote-report.md new file mode 100644 index 00000000..c7717ad4 --- /dev/null +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/8-verify-remote-report.md @@ -0,0 +1,95 @@ +# Verify Remote Report + +# Genesis Oracle + +- Status: Draft +- Created: 2023-01-12 +- Modified: 2023-01-12 +- Authors + - Gyuguen Jang <gyuguen.jang@medibloc.org> + - Youngjoon Lee <yjlee@medibloc.org> + - Hansol Lee <hansol@medibloc.org> + - Myongsik Gong <myongsik_gong@medibloc.org> + - Inchul Song <icsong@medibloc.org> + + +## Synopsis + +This document describes how to validate remote reports generated by Oracle. + +## Remote Report + +Remote reports are one of the core of our protocol. This remote report must be submitted when the genesis oracle or new oracle participant registers to Panacea. A remote report can verify that the genesis oracle or new oracle participant is the correct oracle. + +The correct oracle means an oracle with a unique ID agreed upon in Panacea. +If the unique ID changed, it can be determined that it is an invalid oracle. See the [oracle-key-handshake](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md#oracle-key-handshake) documentation for details on this. + +- For the remote report generated by the genesis oracle, you can see [genesis oracle](./3-genesis-oracle.md) section. +- For the remote report generated by the new oracle registration, you can see [oracle registration](./4-oracle-registration.md) section. +- How to verify correct oracle via remote report, you can see [confidential oracle](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md) section. + +### Validation a genesis oracle + +To verify the genesis oracle, you need an oracle public key and a remote report generated based on that oracle public key. This information can be obtained from Panacea's oracle module parameters. +You need to create `public_key_info.json` file through the process below. +```shell +ORACLE_PUBLIC=$(panacead q oracle params --node <node-rpc-address> -o json) +ORACLE_PUBLIC_KEY=$(panacead q oracle params --node <node-rpc-address> -o json | jq -r .params.oracle_public_key) +ORACLE_PUBLIC_REMOTE_REPORT=$(panacead q oracle params --node <node-rpc-address> -o json | jq -r .params.oracle_pub_key_remote_report) + +jq -n --arg public_key_base64 $ORACLE_PUBLIC_KEY --arg remote_report_base64 $ORACLE_PUBLIC_REMOTE_REPORT '{public_key_base64: $public_key_base64, remote_report_base64: $remote_report_base64}' > public_key_info.json +``` + +**oracle_public_key_info.json** +```json +{ + "public_key_base64": "<public-key-base64>", + "remote_report_base64": "<remote-report-base64>" +} +``` + +Move the generated json file to the oracle home path and perform remote report validation. +```shell +mv ./oracle_public_key_info.json <directory-you-want>/.oracle + +docker run \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v <directory-you-want>:/oracle \ + ghcr.io/medibloc/panacea-oracle:main \ + ego run /usr/bin/oracled verify-report /home_mnt/.oracle/oracle_public_key_info.json +``` + +**Output** +``` +time="2023-01-12T01:45:45Z" level=info msg="remote report is verified successfully" +``` + +### Validation a new oracle registration + +To verify a newly registered oracle, the public key of the node registered by this oracle and the remote report are required. This information can be found in oracle registration store on Panacea. + +```shell +ORACLE_REGISTRATION=$(panacead q oracle oracle-registration <unique-id> <oracle-address> --node <node-rpc-address> -o json) +NODE_PUBLIC_KEY=$(echo $ORACLE_REGISTRATION | jq -r .oracle_registration.node_pub_key) +NODE_PUBLIC_REMOTE_REPORT=$(echo $ORACLE_REGISTRATION | jq -r .oracle_registration.node_pub_key_remote_report) + +jq -n --arg public_key_base64 $NODE_PUBLIC_KEY --arg remote_report_base64 $NODE_PUBLIC_REMOTE_REPORT '{public_key_base64: $public_key_base64, remote_report_base64: $remote_report_base64}' > node_public_key_info.json +``` + +Move the generated json file to the oracle home path and perform remote report validation. +```shell +mv ./node_public_key_info.json <directory-you-want>/.oracle + +docker run \ + --device /dev/sgx_enclave \ + --device /dev/sgx_provision \ + -v <directory-you-want>:/oracle \ + ghcr.io/medibloc/panacea-oracle:main \ + ego run /usr/bin/oracled verify-report /home_mnt/.oracle/oracle_public_key_info.json +``` + +**Output** +```shell +time="2023-01-12T01:45:45Z" level=info msg="remote report is verified successfully" +``` \ No newline at end of file diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index a3543bf8..83335c24 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -71,4 +71,4 @@ * [Running a Node](5-oracles/1-operate-oracle-nodes/5-running-node.md) * [Updating Oracle Information](5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md) * [Oracle Upgrade](5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md) -* FAQ \ No newline at end of file + * [Verify a Remote Report](5-oracles/1-operate-oracle-nodes/8-verify-remote-report.md) \ No newline at end of file From 7d247d83ca6fd033c520f97131e9d21b32d09223 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee <taxihighway@gmail.com> Date: Fri, 13 Jan 2023 15:50:22 +0900 Subject: [PATCH 57/84] remove unnecessary images --- .gitbook/4-validators/3-join-mainnet-testnet.md | 4 ++-- .../images}/ec2-ami.png | Bin .../images}/ec2-instance-type.png | Bin .gitbook/assets/banner.png | Bin 14347 -> 0 bytes .gitbook/assets/image.png | Bin 27081 -> 0 bytes 5 files changed, 2 insertions(+), 2 deletions(-) rename .gitbook/{assets/fullnode => 4-validators/images}/ec2-ami.png (100%) rename .gitbook/{assets/fullnode => 4-validators/images}/ec2-instance-type.png (100%) delete mode 100644 .gitbook/assets/banner.png delete mode 100644 .gitbook/assets/image.png diff --git a/.gitbook/4-validators/3-join-mainnet-testnet.md b/.gitbook/4-validators/3-join-mainnet-testnet.md index 2f1423af..56ca4447 100644 --- a/.gitbook/4-validators/3-join-mainnet-testnet.md +++ b/.gitbook/4-validators/3-join-mainnet-testnet.md @@ -9,13 +9,13 @@ This tutorial introduces deploying a new node on [AWS](https://aws.amazon.com/) Choose Ubuntu Server 20.04 LTS 64-bit (x86) with SSD Volume Type. -![](../assets/fullnode/ec2-ami.png) +![](images/ec2-ami.png) ### Choose the instance type Choose the `m5.large` instance type (minimum spec). -![](../assets/fullnode/ec2-instance-type.png) +![](images/ec2-instance-type.png) ### Configure instance details diff --git a/.gitbook/assets/fullnode/ec2-ami.png b/.gitbook/4-validators/images/ec2-ami.png similarity index 100% rename from .gitbook/assets/fullnode/ec2-ami.png rename to .gitbook/4-validators/images/ec2-ami.png diff --git a/.gitbook/assets/fullnode/ec2-instance-type.png b/.gitbook/4-validators/images/ec2-instance-type.png similarity index 100% rename from .gitbook/assets/fullnode/ec2-instance-type.png rename to .gitbook/4-validators/images/ec2-instance-type.png diff --git a/.gitbook/assets/banner.png b/.gitbook/assets/banner.png deleted file mode 100644 index a2436968821d084bf0431d977c0950fe8bde663b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14347 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 b@Q9#|mtk7xin^aJ2B#>eCR-%)?DhWwP6N#F diff --git a/.gitbook/assets/image.png b/.gitbook/assets/image.png deleted file mode 100644 index bcf69bf5debe2d8ff2ddca7cc094fb6e6711f980..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27081 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 From b3ac6d1cc550c2bc2c4b2baef447df30b96f0a0f Mon Sep 17 00:00:00 2001 From: Youngjoon Lee <taxihighway@gmail.com> Date: Fri, 13 Jan 2023 15:56:16 +0900 Subject: [PATCH 58/84] add tj --- .gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md | 1 + .gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md | 1 + .../1-dep-specs/3-data-provider-consent.md | 11 ++++++----- .../3-protocol-devs/1-dep-specs/4-data-validation.md | 11 ++++++----- .../1-dep-specs/5-confidential-oracle.md | 11 ++++++----- .gitbook/3-protocol-devs/1-dep-specs/6-incentives.md | 11 ++++++----- 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md index 17d14e9c..18c09597 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md @@ -9,6 +9,7 @@ - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - Inchul Song <icsong@medibloc.org> + - Taejin Yoon <tj@medibloc.org> ## Synopsis diff --git a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md index a0047cef..310fa905 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md @@ -9,6 +9,7 @@ - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - Inchul Song <icsong@medibloc.org> + - Taejin Yoon <tj@medibloc.org> ## Synopsis diff --git a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md index 72a99850..6c85c9be 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md @@ -4,11 +4,12 @@ - Crated: 2023-01-04 - Modified: 2023-01-04 - Authors - - Youngjoon Lee <yjlee@medibloc.org> - - Gyuguen Jang <gyuguen.jang@medibloc.org> - - Hansol Lee <hansol@medibloc.org> - - Myongsik Gong <myongsik_gong@medibloc.org> - - Inchul Song <icsong@medibloc.org> + - Youngjoon Lee <yjlee@medibloc.org> + - Gyuguen Jang <gyuguen.jang@medibloc.org> + - Hansol Lee <hansol@medibloc.org> + - Myongsik Gong <myongsik_gong@medibloc.org> + - Inchul Song <icsong@medibloc.org> + - Taejin Yoon <tj@medibloc.org> ## Synopsis diff --git a/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md b/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md index 7dc2d27c..98829b6f 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md @@ -4,11 +4,12 @@ - Created: 2023-01-04 - Modified: 2023-01-04 - Authors - - Gyuguen Jang <gyuguen.jang@medibloc.org> - - Youngjoon Lee <yjlee@medibloc.org> - - Hansol Lee <hansol@medibloc.org> - - Myongsik Gong <myongsik_gong@medibloc.org> - - Inchul Song <icsong@medibloc.org> + - Gyuguen Jang <gyuguen.jang@medibloc.org> + - Youngjoon Lee <yjlee@medibloc.org> + - Hansol Lee <hansol@medibloc.org> + - Myongsik Gong <myongsik_gong@medibloc.org> + - Inchul Song <icsong@medibloc.org> + - Taejin Yoon <tj@medibloc.org> ## Synopsis diff --git a/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md b/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md index ed1eaef2..3ddd9417 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md @@ -4,11 +4,12 @@ - Created: 2023-01-06 - Modified: 2023-01-06 - Authors - - Inchul Song <icsong@medibloc.org> - - Youngjoon Lee <yjlee@medibloc.org> - - Gyuguen Jang <gyuguen.jang@medibloc.org> - - Hansol Lee <hansol@medibloc.org> - - Myongsik Gong <myongsik_gong@medibloc.org> + - Inchul Song <icsong@medibloc.org> + - Youngjoon Lee <yjlee@medibloc.org> + - Gyuguen Jang <gyuguen.jang@medibloc.org> + - Hansol Lee <hansol@medibloc.org> + - Myongsik Gong <myongsik_gong@medibloc.org> + - Taejin Yoon <tj@medibloc.org> ## Synopsis diff --git a/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md b/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md index 7985eda7..e06abef9 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md @@ -4,11 +4,12 @@ - Created: 2023-01-06 - Modified: 2023-01-06 - Authors - - Youngjoon Lee <yjlee@medibloc.org> - - Gyuguen Jang <gyuguen.jang@medibloc.org> - - Hansol Lee <hansol@medibloc.org> - - Myongsik Gong <myongsik_gong@medibloc.org> - - Inchul Song <icsong@medibloc.org> + - Youngjoon Lee <yjlee@medibloc.org> + - Gyuguen Jang <gyuguen.jang@medibloc.org> + - Hansol Lee <hansol@medibloc.org> + - Myongsik Gong <myongsik_gong@medibloc.org> + - Inchul Song <icsong@medibloc.org> + - Taejin Yoon <tj@medibloc.org> ## Synopsis From d5b448c428c2bcad30c81f42a7446e1dba26f76b Mon Sep 17 00:00:00 2001 From: Hansol Lee <38912532+H4NLee@users.noreply.github.com> Date: Fri, 13 Jan 2023 18:14:22 +0900 Subject: [PATCH 59/84] docs: add terms of agreement (#621) --- .../1-users/3-data-exchange/1-consume-data.md | 11 +++++++-- .../1-users/3-data-exchange/2-provide-data.md | 24 ++++++++++++++++--- .../1-dep-specs/2-data-deal.md | 12 +++++++++- .../1-dep-specs/3-data-provider-consent.md | 12 ++++++++-- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 26337d3d..c6a18943 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -27,14 +27,21 @@ For `deal-file-path`, create a following JSON file. "amount": "1000000" }, "max_num_data": 10, - "consumer_address": "panacea1..." + "consumer_address": "panacea1...", + "agreement_terms": [ + { + "id": 1, + "required": true, + "title": "Terms of data provision", + "description": "The provided data will be used for ..." + } + ] } ``` It is very important to set data schema specifically and correctly, so that data being provided can be validated accurately by oracles. For more details about data deals, please see the [Data Deal](../../3-protocol-devs/1-dep-specs/2-data-deal.md) specification. - ## Query deals You can query a deal with its deal ID. diff --git a/.gitbook/1-users/3-data-exchange/2-provide-data.md b/.gitbook/1-users/3-data-exchange/2-provide-data.md index c58527b3..8830585e 100644 --- a/.gitbook/1-users/3-data-exchange/2-provide-data.md +++ b/.gitbook/1-users/3-data-exchange/2-provide-data.md @@ -65,7 +65,7 @@ The certificate form is like below: "cid" : "{ipfs-cid}", "unique_id" : "{oracle-unique-id}", "oracle_address" : "{oracle-address}", - "deal_id": "{deal-id}", + "deal_id": <deal-id>, "provider_address" : "{your-address}", "data_hash" : "{data-hash}" }, @@ -76,9 +76,27 @@ Now you can use this certificate in the next step. ## Submit consent -Broadcast the following `submit-consent` transaction with certificate from oracle. +Broadcast the following `submit-consent` transaction with the certificate from oracle and agreements of terms for data provision. + +**consent.json** + +```json +{ + "deal_id": <deal-id>, + "certificate": { + ... + }, + "agreements": [ + { + "id": 1, + "agreement": true + } + ] +} +``` + ```bash -panacead submit-consent ${certificate-file-path} \ +panacead submit-consent ${consent-file-path} \ --from ${data-provider-addr} \ --chain-id ${chain-id} \ --gas auto --gas-adjustment 1.30 --gas-prices 5umed \ diff --git a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md index 310fa905..a9d927c0 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md @@ -48,7 +48,15 @@ message Deal { uint64 max_num_data = 5; uint64 cur_num_data = 6; string consumer_address = 7; - DealStatus status = 8; + repeated AgreementTerm agreement_terms = 8; + DealStatus status = 9; +} + +message AgreementTerm { + uint32 id = 1; + bool required = 2; + string title = 3; + string description = 4; } ``` @@ -59,6 +67,7 @@ message Deal { - `max_num_data`: The maximum number of data the consumer want - `cur_num_data`: The current number of data provided - `consumer_address`: A consumer's account address of the form `panacea1...` +- `agreement_terms`: Terms of agreement of data provision - `status`: The status of deal. 3 statuses can be possible - `DEAL_STATUS_ACTIVE`: The status when deal is active (`cur_num_data` < `max_num_data`). - `DEAL_STATUS_INACTIVE`: The status when deal is deactivated (when consumer deactivated the deal) @@ -74,6 +83,7 @@ message MsgCreateDeal { cosmos.base.v1beta1.Coin budget = 2; uint64 max_num_data = 3; string consumer_address = 4; + repeated AgreementTerm agreement_terms = 5; } ``` diff --git a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md index 6c85c9be..19ccaba2 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md @@ -53,7 +53,7 @@ message UnsignedCertificate { } ``` -Using the `Certificate`, provider can submit consent to provide the data. +Using the `Certificate`, provider can submit consent to provide the data with agreement of terms. ```proto message MsgSubmitConsent { @@ -61,7 +61,14 @@ message MsgSubmitConsent { } message Consent { - Certificate certificate = 1; + uint64 deal_id = 1; + Certificate certificate = 2; + repeated Agreement agreements = 3; +} + +message Agreement { + uint32 term_id = 1; + bool agreement = 2; } ``` @@ -69,6 +76,7 @@ When this consent is submitted, blockchain will check: - if the data is provided by the owner of the data - if the data is validated by a registered and active oracle - if the data is provided in duplicate +- if the provider agrees to the required terms of agreement If all checks pass, rewards are distributed to the provider and oracle(more about [incentive](./6-incentives.md)). From 579815701aeac911d3d56b774d48b745179a475e Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Wed, 18 Jan 2023 14:25:19 +0900 Subject: [PATCH 60/84] Update 0-panacea-ecosystem.md Grammar check done. @youngjoon-lee If you could take a look at the last section ### Secure Data Storage, it would be greatly appreciated. --- .../0-about-panacea/0-panacea-ecosystem.md | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/.gitbook/0-about-panacea/0-panacea-ecosystem.md b/.gitbook/0-about-panacea/0-panacea-ecosystem.md index 0bea0b2b..b52771cb 100644 --- a/.gitbook/0-about-panacea/0-panacea-ecosystem.md +++ b/.gitbook/0-about-panacea/0-panacea-ecosystem.md @@ -3,12 +3,12 @@ ## Mission -Allow patients to own their data, provide it, and get incentivized. +Allow patients to own their data, provide the data to data consumers, and get incentivized. ## Goal -Building decentralized healthcare data sharing/exchange protocols +Build decentralized healthcare data sharing/exchange protocols ## Tech Stack @@ -18,7 +18,7 @@ Building decentralized healthcare data sharing/exchange protocols ## Panacea blockchain -The Panacea is a public blockchain based on the Cosmos SDK and the Tendermint. +Panacea is a public blockchain based on the Cosmos SDK and the Tendermint. As the Tendermint implements a partially synchronous BFT (Byzantine fault-tolerant) consensus protocol, Panacea can provide a high-performance, consistent, and secure decentralized network @@ -51,11 +51,11 @@ Then, data verifiers (receivers) can verify that the data has been not tampered ### Data Exchange Coordination Panacea provides a feature of coordinating data exchange deals. -Data consumers can publish deals publicly, specifying which data they want to purchase and how much budget they are willing to pay. -And, data providers (holders) who agree to provide their data with consumers can provide their data securely and earn rewards in MED. +Data consumers can publish deals publicly, specifying 1) which data they want to purchase and 2) how much budget they are willing to pay. +Data providers (holders) who agree to provide their data with the data consumers can provide their data securely and earn MED as rewards. -This on-chain data exchange coordination must work with some off-chain components to verify data validity/integrity and securely deliver data. -For example, some malicious data providers can try to sell data that data consumers don't want or data that was generated by themselves (not by trusted issuers). +This on-chain data exchange coordination must work with some off-chain components to verify data validity/integrity and to deliver data securely. +For example, some malicious data providers ccould try to sell data that the data consumers don't want or that was forged by themselves (not by trusted issuers). Therefore, data should be validated by off-chain data validators before being delivered to data consumers, as described in the [Data Exchange Validation](#data-exchange-validation-with-confidential-computing) section. @@ -67,30 +67,26 @@ Using [Panacea Verifiable Credential SDK](https://github.com/medibloc/vc-sdk), d Since [Verifiable Credential](https://www.w3.org/TR/vc-data-model/) is a standard format defined by W3C, any data receivers can verify credentials without any compatibility issues using the data issuer's (holder's) cryptographic public key that is corresponding with their DID. In other words, the Verifiable Credential SDK works with DID management features of the Panacea blockchain. -In addition, data holders can present their data by masking privacy-sensitive fields that don't need to be revealed. -That can be achieved by Zero-knowledge Proof using BBS+ signatures so that data receivers can verify data integrity even though some fields in the data are masked (technically, ' tampered'). +In addition, data holders can present their data while masking privacy-sensitive fields. +This can be achieved by Zero-knowledge Proof using BBS+ signatures so that data receivers can verify data integrity even though some fields in the data are masked (technically, ' tampered'). ### Data Exchange Validation with Confidential Computing As described in the [Data Exchange Coordination](#data-exchange-coordination) section, Panacea blockchain provides data exchange coordination. However, data that is exchanged between providers and consumers cannot be validated/delivered through a public blockchain because all transaction data is exposed to everyone. Even if transaction data is encrypted, validator nodes should be able to decrypt data to verify data validity/integrity. That could be a huge vulnerability, allowing data to be leaked to anyone other than intended data consumers. -To avoid this vulnerability, we could implement this data exchange validation as smart contracts run on [Secret Network](https://scrt.network/), but still, we didn't want to expose private data on the public blockchain even if all data is encrypted. +To avoid this vulnerability, we could have implemented this data exchange validation as smart contracts run on [Secret Network](https://scrt.network/), but still, we didn't want to expose private data on the public blockchain even if all data is encrypted. Instead of solving this problem on chain, we have introduced an off-chain decentralized oracle powered by confidential computing ([Intel SGX](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/overview.html)). Like Secret Network, all oracle nodes are run in the secure enclave. All data is encrypted so that only oracle nodes can decrypt it to verify data validity/integrity. If data is verified successfully, it is re-encrypted by oracle nodes for the data consumer. Because this process is executed in the secure enclave, decrypted data cannot be stolen by anyone, even oracle node operators. -To avoid the Byzantine problem between decentralized oracle nodes, oracle nodes borrow the voting power from the Panacea blockchain. -Only operators who are running validators on Panacea can run oracle nodes. Then, an oracle node has the same voting power as a corresponding validator. -If an oracle node acts maliciously, its validator's stake is slashed. - ### Secure Data Storage -Based on DIDs, Verifiable Credentials, and Data Exchange Coordination/Validation, it seems that applications that handle privacy data can be implemented. -However, to actually implement applications, it must be decided specifically how data will be stored and how it will be transmitted in decentralized environments. +Based on DIDs, Verifiable Credentials, and Data Exchange Coordination/Validation, it seems that applications that handle privacy data can be implemented on top of Panacea. +However, to actually implement applications, the specific method on how data will be stored and how it will be transmitted in decentralized environments should be decided. Thanks to [IPFS](https://ipfs.io/), data can be transmitted by [content addressing](https://docs.ipfs.tech/concepts/content-addressing/) in environments where ecosystem participants don't know each other's IP addresses and ports. -But, IPFS is also a public network basically that is unsuitable for storing privacy data even if it is encrypted. IPFS also provides a way to set up private clusters, but it is not flexible enough to be used for data exchange based on public blockchains. +However, IPFS is also a public network, which is unsuitable for storing privacy data even if it is encrypted. IPFS also provides a way to set up private clusters, but it is not flexible enough to be used for based on public blockchains. -MediBloc team is researching many secure decentralized data storages including edge databases. \ No newline at end of file +To solve this problem, MediBloc team is still researching many secure decentralized data storages including edge databases. From a3e26aaa1103dac647c6d7132f7758deec8c2e49 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Wed, 18 Jan 2023 14:39:34 +0900 Subject: [PATCH 61/84] Update 1-roadmap.md This section should either be rewritten or be left as is and tagged to a newer version with explanation on what changed. Would like to get team's feedback on this. --- .gitbook/0-about-panacea/1-roadmap.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitbook/0-about-panacea/1-roadmap.md b/.gitbook/0-about-panacea/1-roadmap.md index 976821b3..747319ec 100644 --- a/.gitbook/0-about-panacea/1-roadmap.md +++ b/.gitbook/0-about-panacea/1-roadmap.md @@ -18,3 +18,5 @@ The detailed tech stack of the data exchange protocol is described in the [Panac There will be more detailed issues that we would have to solve, and we know that all of them cannot be solved in one step. Hence, we will complete this big task step by step. In 2022, MediBloc have released the v0 of data exchange protocol as a proof of concept that includes only essential features on testnet. Based on this proof of concepts, the data exchange protocol will be improved as v1 in 2023 with enhanced security and interoperability. Also, MediBloc will be introducing dApps for data providers using data exchange protocol and keep designing the services that go on top of data exchange protocol. MediBloc has already opened all source codes and progresses publicly on GitHub. We encourage anyone to join the project and share your insights. We are so excited and thrilled to share our vision to achieve our goal to become the world’s best patient centric health data platform. Thank you for your continued support! + +-- From 465217690784e646fa7250a2ff3e7a851a1f1482 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Wed, 18 Jan 2023 14:51:34 +0900 Subject: [PATCH 62/84] Update 0-about-dep.md Grammar check --- .gitbook/1-users/3-data-exchange/0-about-dep.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitbook/1-users/3-data-exchange/0-about-dep.md b/.gitbook/1-users/3-data-exchange/0-about-dep.md index d696e862..456e4600 100644 --- a/.gitbook/1-users/3-data-exchange/0-about-dep.md +++ b/.gitbook/1-users/3-data-exchange/0-about-dep.md @@ -10,10 +10,10 @@ Data consumers can open data deals by specifying the type, the quantity, and the Data providers can choose and participate in the deals that match the data that they have when they are willing to provide. -To guarantee data consumers only consume data in the form they want, +To guarantee data consumers only receive the data that match the criteria specified by them, decentralized oracles verify and issue certificates for all data being provided by the data provider. -Panacea public blockchain manages the status of all data deals and data sharing consents, +Panacea manages the status of all data deals and data sharing consents, ensuring data providers and ecosystem operators are rewarded appropriately. @@ -25,8 +25,8 @@ The ultimate goal of owning our own data is having a control about how our data ### Decentralized off-chain data validation -To ensure data consumers can only consume data that they want, all data being shared must be validated by -decentralized players who are not malicious. +o guarantee data consumers only receive the data that match the criteria specified by them, +decentralized oracles verify and issue certificates for all data being provided by the data provider. ### Privacy @@ -40,4 +40,4 @@ Not only healthcare data, but various types of data should be covered through th ### Open-sourced protocol All protocol specifications and implementations must be open-sourced, so any participants can understand -how data is exchanged and how privacy is guaranteed. \ No newline at end of file +how data is exchanged and how privacy is guaranteed. From a03df74fc27f81fb1980ad0e85458ab177920233 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:04:55 +0900 Subject: [PATCH 63/84] Update 1-consume-data.md Grammar check --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index c6a18943..96c6c740 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -7,7 +7,7 @@ Data deals are registered in the Panacea public blockchain, so all data provider ## Create a data deal -Broadcast the following `create-deal` transaction with specifying data schema, a data count, and a budget in the deal-file in JSON format. +Broadcast the following `create-deal` transaction with desired data schema and count, and budget specified in the deal-file in JSON format. ```bash panacead tx datadeal create-deal ${deal-file-path} \ --from ${data-consumer-addr} \ @@ -38,7 +38,7 @@ For `deal-file-path`, create a following JSON file. ] } ``` -It is very important to set data schema specifically and correctly, so that data being provided can be validated accurately by oracles. +It is very important to set data schema specifically and correctly, so that data being provided can be validated accurately by the oracles. For more details about data deals, please see the [Data Deal](../../3-protocol-devs/1-dep-specs/2-data-deal.md) specification. @@ -49,7 +49,7 @@ You can query a deal with its deal ID. panacead query datadeal deal ${deal-id} \ --node ${chain-node-rpc-addr} ``` -Also, you can query all deals registered in the chain. +You can also query all deals registered in the chain. ```bash panacead query datadeal deals \ --node ${chain-node-rpc-addr} @@ -60,7 +60,7 @@ panacead query datadeal deals \ If some data providers have data that fit the requirements of your data deal, they will submit consents to the chain. The consent means that the data provider has agreed to provide their data to a specific data consumer. -Also, each consent can contain a data validation certificate issued by an oracle, so that data consumers can trust the validity of data. +Also, each consent should contain a data validation certificate issued by an oracle, so that data consumers can trust the validity of data. As soon as data providers submit their consents, you can query all consents submitted to a specific data deal. ```bash @@ -78,7 +78,7 @@ For more details about data consents, please see the [Data Provider Consent](../ ## Access data -A data validation certificate issued by an oracle contains the methods to access the data. +A data validation certificate issued by an oracle should contain the methods to access the data. For example, if the oracle decides to transmit data via [IPFS](https://ipfs.tech/), the certificate will contain a [CID](https://docs.ipfs.io/concepts/content-addressing/) of data. If so, you can access any IPFS node connected to the public IPFS network, and obtain the data. @@ -104,7 +104,7 @@ panacead issue-jwt ${expiration-duration} --from ${your-account-key-name} ``` Please note that the returned secret key is also encrypted, so that only the specific data consumers can decrypt the key using his/her chain account private key. -Nevertheless, we highly recommend you to communicate with oracles who provides an HTTPS endpoint with SSL/TLS encryption. +Nevertheless, we highly recommend you to communicate with oracles who provide an HTTPS endpoint with SSL/TLS encryption. Using the encrypted secret key that you obtained from the oracle, you can decrypt data by the following CLI. ```bash From 069ef75bfbee1274eace3c721143f200ee8c8e1d Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:16:44 +0900 Subject: [PATCH 64/84] Update 2-provide-data.md Grammar check --- .gitbook/1-users/3-data-exchange/2-provide-data.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitbook/1-users/3-data-exchange/2-provide-data.md b/.gitbook/1-users/3-data-exchange/2-provide-data.md index 8830585e..3192859a 100644 --- a/.gitbook/1-users/3-data-exchange/2-provide-data.md +++ b/.gitbook/1-users/3-data-exchange/2-provide-data.md @@ -1,18 +1,18 @@ # Provide data -Data providers can provide their data that match the requirements of the data deal and in return earn a reward. +Data providers can provide their data that match the requirements of the data deal and, in return, earn a reward in MED. Since only the data verified by oracle can be provided to a deal, providers should first request data verification to oracle. -As a result of verification, oracle will issue a certificate, then provider can provide their data by submitting a consent with the certificate to Panacea. +As a result of verification, oracle will issue a certificate; then provider can provide their data by submitting a consent with the certificate to Panacea. In the whole process of data transmission, the data is encrypted so that no one can access the original data. -The transmission of data and the payment of rewards are managed atomically through the Panacea, so consumers can get the data only when the reward payment is completed. +The transmission of data and the payment of rewards are managed atomically through Panacea, so consumers can get the data only when the reward payment is completed. ## Request data verification to oracle -Before request to oracle, you should encrypt your data for privacy preserving. +Before requesting data verification to oracle, you (data provider) should encrypt the data to preserve privacy. Encryption can be done using your chain account key and oracle public key which is registered in Panacea. This makes only oracles can decrypt and verify your original data in secure area. For more details about data secure area, please see [Confidential Oracle](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md). @@ -23,7 +23,7 @@ panacead encrypt-data ${input-file-path} ${your-account-key-name} ``` You must specify a JWT issued by yourself in order to prove that you are the data provider. -For that authentication, the JWT must be signed by your (data provider's) chain account private key. +For that authentication, the JWT must be signed by your chain account private key. We highly recommend to set the expiration of JWT as short as possible for security reasons. In the near future, the protocol will adopt the 'nonce' concept to improve the security of authentications. @@ -105,11 +105,11 @@ panacead submit-consent ${consent-file-path} \ After you submit consent, Panacea verifies the certificate and checks the status of the deal. -When the verification is completed, Panacea makes the data accessible to consumers and makes you can get reward. +When the verification is completed, Panacea makes the data accessible to consumers and transmitts rewards to you. ## Query consent You can query a consent by the deal ID and data hash you provided. ```bash panacead query datadeal consent ${deal-id} ${data-hash} \ --node ${chain-node-rpc-addr} -``` \ No newline at end of file +``` From 7d797b81b8e7d9d1c7daf2055f0a84cf21a17309 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:19:00 +0900 Subject: [PATCH 65/84] Update 1-consume-data.md --- .gitbook/1-users/3-data-exchange/1-consume-data.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitbook/1-users/3-data-exchange/1-consume-data.md b/.gitbook/1-users/3-data-exchange/1-consume-data.md index 96c6c740..e2ea94c8 100644 --- a/.gitbook/1-users/3-data-exchange/1-consume-data.md +++ b/.gitbook/1-users/3-data-exchange/1-consume-data.md @@ -44,12 +44,12 @@ For more details about data deals, please see the [Data Deal](../../3-protocol-d ## Query deals -You can query a deal with its deal ID. +One can query a deal with its deal ID. ```bash panacead query datadeal deal ${deal-id} \ --node ${chain-node-rpc-addr} ``` -You can also query all deals registered in the chain. +One can also query all deals registered in the chain. ```bash panacead query datadeal deals \ --node ${chain-node-rpc-addr} @@ -58,11 +58,11 @@ panacead query datadeal deals \ ## Query consents -If some data providers have data that fit the requirements of your data deal, they will submit consents to the chain. +If some data providers have data that fit the requirements of your (data consumers') data deal, they will submit consents to the chain. The consent means that the data provider has agreed to provide their data to a specific data consumer. Also, each consent should contain a data validation certificate issued by an oracle, so that data consumers can trust the validity of data. -As soon as data providers submit their consents, you can query all consents submitted to a specific data deal. +As soon as data providers submit their consents, you (data consumer) can query all consents submitted to a specific data deal. ```bash panacead query datadeal consents ${deal-id} \ --node ${chain-node-rpc-addr} From ef094f831abc2508e0d309e53f3348e25f2eb217 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:40:11 +0900 Subject: [PATCH 66/84] Update 1-user-flow.md Grammar check --- .gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md index 18c09597..c0be8a4d 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/1-user-flow.md @@ -9,12 +9,12 @@ - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - Inchul Song <icsong@medibloc.org> - - Taejin Yoon <tj@medibloc.org> + - Tae Jin Yoon <tj@medibloc.org> ## Synopsis -This document specified the entire user flow in the Data Exchange Protocol (hereafter 'DEP'). +This document specifies the entire user flow in the Data Exchange Protocol (hereafter 'DEP'). This document defines the key players essential to operate the DEP, and describes how the players interact to complete the whole data exchange process. It is recommended to walk through this document first before diving deeply into detailed specifications. @@ -32,10 +32,10 @@ To achieve this goal without centralized/authorized mediators, DEP introduces fo A data consumer is an individual or an organization who wants to consume certain kinds of data for specific purposes, with or without paying. ##### Data Provider -A data provider is an individual or an organization that holds data and the permission to provide data to data consumers to obtain benefits, such as incentives or services. +A data provider is an individual or an organization that holds data and a permission to provide data to data consumers to obtain benefits, such as incentives or services. ##### Oracle (Oracle operator) -An oracle is a data validator that guarantees data validity and integrity while data is delivered from data providers to data consumers. +An oracle is a data validator that guarantees validity and integrity of the data before data is delivered from data providers to data consumers. Data verification is essential to ensure the atomicity of data delivery and incentive payments. ##### Panacea Blockchain Validator @@ -100,4 +100,4 @@ None at present. ## Copyright -All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). From 4d2f1c056f678f91f45af349a3deef5732b702ae Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:54:36 +0900 Subject: [PATCH 67/84] Update 2-data-deal.md Grammar --- .../1-dep-specs/2-data-deal.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md index a9d927c0..4af4bac0 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md @@ -9,21 +9,21 @@ - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - Inchul Song <icsong@medibloc.org> - - Taejin Yoon <tj@medibloc.org> + - Tae Jin Yoon <tj@medibloc.org> ## Synopsis -This document defines a data deal which is a contract for data collecting and pay for provision in [DEP](../../1-users/3-data-exchange/0-about-dep.md). +This document defines a data deal which is a contract for data collecting and payment for data provision in [DEP](../../1-users/3-data-exchange/0-about-dep.md). Data consumers create data deals by specifying the type, the quantity, and the pricing of the data that they are willing to consume. -Data providers can provide their data to the deals that match the type of data they have. +Data providers can choose and participate in the deals that match the data that they have when they are willing to provide. When a data provider provides data to the deal, the payout is distributed to the provider and the oracle that validated the data. Also, data consumers can deactivate their data deal whenever they want and the remained budget would be refunded to the consumer's account. ### Motivation -Data consumers want different types of data, and even for the same type of data, they all differ in how much they want and how much they are willing to pay. -Thus, the data deal was devised so that data consumers can determine the type of data they want, as much as they want, at a cost they want. +Data consumers want different types of data, and even for the same type of data, they all differ in the desired quantity and desired cost of the data. +Thus, the data deal was devised so that data consumers can determine the type of data they want, the quantity they want, and the cost level they want. ### Definitions @@ -32,8 +32,8 @@ Thus, the data deal was devised so that data consumers can determine the type of ## Technical Specification Data consumers should be able to post the information described below publicly, so that any data provider can see it. -Also, data providers should be able to be assured that a particular data consumer really posted the information. -To meet these requirements, it is recommended to use a public decentralized state machine as a single point of truth, such as Panacea. +Also, data providers should be assured that a particular data consumer really posted the information. +To meet these requirements, it is recommended to use a public decentralized state machine as a single source of truth, such as Panacea. ### Data Structure of Deal @@ -94,7 +94,7 @@ In other words, the balance of consumer's account should be greater or equal tha The consumer who created the deal can deactivate the deal at any time as long as `max_num_data` of data is not provided. -To deactivate deal, the id of deal should be specified. +To deactivate a deal, the id of the deal should be specified. ```proto message MsgDeactivateDeal { @@ -103,8 +103,8 @@ message MsgDeactivateDeal { } ``` -When deal is deactivated, all the remained budget is refunded to the consumer's account. -After deal is deactivated, no providers can provide their data to this deal, and the status of the deal would be `DEAL_STATUS_INACTIVE`. +When a deal is deactivated, all ramining budget is refunded to the data consumer's account. +After the deal is deactivated, data providers cannot provide their data to this deal, and the status of the deal changes to `DEAL_STATUS_INACTIVE`. ## Backwards Compatibility @@ -129,4 +129,4 @@ None at present. ## Copyright -All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). From 220a53589e4f006bc60cddeb2f06a9adb57363bc Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Thu, 19 Jan 2023 10:07:23 +0900 Subject: [PATCH 68/84] Update 3-data-provider-consent.md --- .../1-dep-specs/3-data-provider-consent.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md index 19ccaba2..8f7b9a1b 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md @@ -9,14 +9,15 @@ - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - Inchul Song <icsong@medibloc.org> - - Taejin Yoon <tj@medibloc.org> + - Tae Jin Yoon <tj@medibloc.org> ## Synopsis This document is about providing data through [DEP](../../1-users/3-data-exchange/0-about-dep.md). -Before providers provide their data to consumers, the data must be validated from oracle whether the data is the correct data specified in the deal. -Providers can send a request for validation to one of the oracles registered in Panacea, and the oracle will validate the data using confidential computing without any exposure of the data. +Before data providers provide their data to data consumers, the data must be validated by oracle whether the data provided match the data type specified in the deal. + +Data providers can send a request for validation to one of the oracles registered in Panacea, and the oracle will validate the data using confidential computing without any exposure to the data. As a result of a data validation, oracle will issue a certificate to the provider. Providers can consent to provide their data by submitting the certificate to Panacea, and will be rewarded by providing the data. In all of these processes, the data is transmitted with encryption and stored off-chain. @@ -102,4 +103,4 @@ None at present. ## Copyright -All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). From 91d180e76419b9fbb4c3878874afcf6f572c6c96 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Thu, 19 Jan 2023 13:59:13 +0900 Subject: [PATCH 69/84] Update 3-data-provider-consent.md Grammar check --- .../1-dep-specs/3-data-provider-consent.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md index 8f7b9a1b..559e54cf 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/3-data-provider-consent.md @@ -15,10 +15,10 @@ ## Synopsis This document is about providing data through [DEP](../../1-users/3-data-exchange/0-about-dep.md). -Before data providers provide their data to data consumers, the data must be validated by oracle whether the data provided match the data type specified in the deal. +Before data providers provide their data to data consumers, the data must be validated by oracle whether it matches the data type specified in the deal. Data providers can send a request for validation to one of the oracles registered in Panacea, and the oracle will validate the data using confidential computing without any exposure to the data. -As a result of a data validation, oracle will issue a certificate to the provider. +As a result of the data validation, oracle will issue a certificate to the provider. Providers can consent to provide their data by submitting the certificate to Panacea, and will be rewarded by providing the data. In all of these processes, the data is transmitted with encryption and stored off-chain. @@ -35,8 +35,8 @@ To do so, providers use digital signature as consent to provide the data. ## Technical Specification -Before provider provides the data to deal, data should be validated by the oracle. -If the data is successfully validated to be provided, the provider will have a `Certificate` like below (more about [Data Validation](./4-data-validation.md)): +Before a data provider provides data to a deal, the data should be validated by the oracle. +If the data is successfully validated, the provider will receive a `Certificate` like below (more about [Data Validation](./4-data-validation.md)): ```proto message Certificate { @@ -54,7 +54,7 @@ message UnsignedCertificate { } ``` -Using the `Certificate`, provider can submit consent to provide the data with agreement of terms. +Using the `Certificate`, the data provider can submit a consent to provide the data with agreement of terms. ```proto message MsgSubmitConsent { @@ -79,7 +79,7 @@ When this consent is submitted, blockchain will check: - if the data is provided in duplicate - if the provider agrees to the required terms of agreement -If all checks pass, rewards are distributed to the provider and oracle(more about [incentive](./6-incentives.md)). +If all checks pass, rewards are distributed to the data provider and the oracle(more about [incentive](./6-incentives.md)). ## Backwards Compatibility From b44506e0378551be6a879e0726c9b4dfb9324a17 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Thu, 19 Jan 2023 14:13:08 +0900 Subject: [PATCH 70/84] Update 4-data-validation.md Grammar check --- .../1-dep-specs/4-data-validation.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md b/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md index 98829b6f..d7878997 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/4-data-validation.md @@ -9,17 +9,17 @@ - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - Inchul Song <icsong@medibloc.org> - - Taejin Yoon <tj@medibloc.org> + - Tae Jin Yoon <tj@medibloc.org> ## Synopsis -This document describes the API specification, data verification, and process for issuing certificates. +This document describes the API specification, data verification, and certificate issuance. ### Motivation Data consumers can define their requirements. -This requirement allows them to define the data in any format they want. -DEP supports a `JSON schema` to define these requirements. +This requirement allows them to define the format of the data they want. +DEP supports `JSON schema` to define these requirements. Oracle can verify the requirements of data consumers according to this JSON schema specification. Oracle issues a certificate upon successful verification, which can be verified by Panacea. @@ -115,7 +115,7 @@ compare(provider_address, jwtToken.issuer) The deal information can be retrieved from Panacea using the deal ID -Before verifying the data, it is checked whether the deal status is valid. +Before verifying the data, Oracle should check whether the deal status is valid. If the Deal's status is invalid, oracle does not perform verification work. ``` compare(deal.status, 'DEAL_STATUS_ACTIVE') @@ -133,7 +133,7 @@ JSONSchema.Validate(data_schema, orginal_data) If data validation is successful, the data must be re-encrypted and stored on IPFS to be delivered to the consumer. -To re-encrypt the data, a symmetric secret key must be used. The symmetric secret key can be derived by the following logic. +To re-encrypt the data, a symmetric secret key must be used. The symmetric secret key can be derived from the following logic. ``` deal_id_bz = convertUint64ToBigEndian(deal_id) secret_key = SHA256(append(oracle_private_key, deal_id_bz, data_hash)) @@ -166,8 +166,7 @@ The certificate includes the following contents. } ``` -The certificate requires a signature signed with `oracle_private_key`. -Because Panacea needs to be able to verify that the certificate was generated by a trusted oracle. +The certificate requires a signature signed with `oracle_private_key` because Panacea needs to be able to verify that the certificate was generated by a trusted oracle. The `oracle_public_key` registered in Panacea is a pair with the `oracle_private_key` of a trusted oracle. So, Panacea can verify signature of the certificate with `oracle_public_key` to ensure that the certificate is correct. @@ -199,4 +198,4 @@ None at present. ## Copyright -All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). From 13b8c58d5b1a63d567eaa8ac86d224f55f1a3f84 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Thu, 19 Jan 2023 16:12:24 +0900 Subject: [PATCH 71/84] Update 2-data-deal.md --- .gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md index 4af4bac0..2e97da5a 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/2-data-deal.md @@ -18,7 +18,7 @@ This document defines a data deal which is a contract for data collecting and pa Data consumers create data deals by specifying the type, the quantity, and the pricing of the data that they are willing to consume. Data providers can choose and participate in the deals that match the data that they have when they are willing to provide. When a data provider provides data to the deal, the payout is distributed to the provider and the oracle that validated the data. -Also, data consumers can deactivate their data deal whenever they want and the remained budget would be refunded to the consumer's account. +Also, data consumers can deactivate their data deal whenever they want and the remaining budget would be refunded to the consumer's account. ### Motivation From 6090c08af805a48a23125eab6159c28014a55419 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Thu, 19 Jan 2023 16:20:24 +0900 Subject: [PATCH 72/84] Update 6-incentives.md Grammar check --- .../1-dep-specs/6-incentives.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md b/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md index e06abef9..7d5e5b4d 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md @@ -9,18 +9,18 @@ - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - Inchul Song <icsong@medibloc.org> - - Taejin Yoon <tj@medibloc.org> + - Tae Jin Yoon <tj@medibloc.org> ## Synopsis -When data deal is created, a budget for data is deposited from data consumer account. -And the deposit is distributed to the data providers and the oracles that verified the data. -Data consumers also can [deactivate the deal](./2-data-deal.md#Deactivate-Data-Deal) they created and refund the remaining budget at any time if the deal is in status `DEAL_STATUS_ACTIVE`. +When a data deal is created, a budget for the data is deposited from the data consumer account. +The deposit, proposed by the data consumer, is distributed to the data providers and the oracles that verified the data when the data provider submits a consent with the certificate to Panacea. +Data consumers can [deactivate the deal](./2-data-deal.md#Deactivate-Data-Deal) that they created and retrieve the remaining budget at any time if the deal is in status `DEAL_STATUS_ACTIVE`. ### Motivation -This is for transparent distribution for the cost of providing data and the cost of verifying data. +This is for a transparent distribution of the incentives for providing the data and verifying the data. ### Definitions @@ -30,22 +30,22 @@ This is for transparent distribution for the cost of providing data and the cost ### Budget Deposit -When data consumers [create a deal](./2-data-deal.md#create-data-deal), they specify the budget for data provision. -At this time, the amount of the budget is transferred from consumer account to deal account. +When data consumers [create a deal](./2-data-deal.md#create-data-deal), they specify a budget for data provision. +At this time, the total amount of the budget is transferred from the data consumer account to the deal account. ### Reward Distribution When creating a data deal, data consumers specify the quantity as well as the budget for the data. -From this, the price per data can be calculated as: +From these two values, the price per data can be calculated as: ``` price_per_data = deposit / max_num_data ``` -Of the `price_per_data`, as an oracle commission for data verification, the commission rate set by the oracle is transferred to the oracle, and the rest is transferred to the data provider. +When a data provider submits a consent and a certificate, a portion Of the `price_per_data`, is transferred to the oracle and the rest is transferred to the data provider. +This portion is associated with the oracle commision rate that can be set differently for each oracle. -The oracle commission can be set differently for each oracle. -you can find out which oracle verified the data by referring to the [certificate](./4-data-validation.md#Response-Body) submitted by the data provider and how much commission fee to be paid. +The data consumer can find out which oracle verified the data by referring to the [certificate](./4-data-validation.md#Response-Body) submitted by the data provider and how much commission fee was paid. ``` oracle_reward = price_per_data * oracle_commission_rate @@ -54,7 +54,7 @@ provider_reward = price_per_data * (1 - oracle_commission_rate) ### Budget Refund -If consumers want to stop being provided data and refund for the rest of their budget, they can deactivate the deal they created. +If consumers want to stop receiving the data and get refund for the rest of their budget, they can deactivate the deal they created. However, in order to deactivate the deal, the deal must be in the `DEAL_STATUS_ACTIVE` state. ## Backwards Compatibility @@ -79,4 +79,4 @@ None at present. ## Copyright -All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). From f2a546340386309537923baedb89cf45ad6d3ad8 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Thu, 19 Jan 2023 16:20:55 +0900 Subject: [PATCH 73/84] Update 6-incentives.md --- .gitbook/3-protocol-devs/1-dep-specs/6-incentives.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md b/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md index 7d5e5b4d..eeb639bb 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/6-incentives.md @@ -42,7 +42,7 @@ From these two values, the price per data can be calculated as: price_per_data = deposit / max_num_data ``` -When a data provider submits a consent and a certificate, a portion Of the `price_per_data`, is transferred to the oracle and the rest is transferred to the data provider. +When a data provider submits a consent and a certificate, a portion of the `price_per_data`, is transferred to the oracle and the rest is transferred to the data provider. This portion is associated with the oracle commision rate that can be set differently for each oracle. The data consumer can find out which oracle verified the data by referring to the [certificate](./4-data-validation.md#Response-Body) submitted by the data provider and how much commission fee was paid. From 8a364299c20e4f8fa70060f861c2f0c721af96c7 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Thu, 19 Jan 2023 16:58:06 +0900 Subject: [PATCH 74/84] docs: update 5-confidential-oracle.md (#622) Grammar check applied. --- .../1-dep-specs/5-confidential-oracle.md | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md b/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md index 3ddd9417..d26d40db 100644 --- a/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md +++ b/.gitbook/3-protocol-devs/1-dep-specs/5-confidential-oracle.md @@ -9,51 +9,52 @@ - Gyuguen Jang <gyuguen.jang@medibloc.org> - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - - Taejin Yoon <tj@medibloc.org> + - Tae Jin Yoon <tj@medibloc.org> ## Synopsis -This document explains that why the oracles must use confidential computing. +This document explains why the oracles must use confidential computing. ## Motivation In DEP, the data must be verified as explained in the [data validation documentation](./4-data-validation.md). -Verifying data means that the content of data could be shown to the oracle. However, no one would want their data to be -exposed to the oracle for data verification. There may also be malicious oracles to exploit the data unfairly. To -prevent it, we have designed the DEP oracle with confidential computing. Confidential computing guarantees that only +Verifying data means that the content of the data could be shown to the oracle. However, no one would want their data to be +exposed to the oracle for data verification. There may also be malicious oracles that exploit the data unfairly. To +prevent this, we have designed the oracle in DEP with confidential computing. Confidential computing guarantees that only selected code (binary) can access data in the secure enclave. Also, it could protect a sensitive data from being leaked -by malicious operators while verifying a data correctly in decentralized system. +by malicious operators while verifying the data correctly in this decentralized system. ## Confidential Oracle -The oracle operators(human) can see the content of sensitive data. For example, if the oracle software stores the -important sensitive data to the disk or storage without sealing it, it can be read by anyone who can access the disk or -storage. So we developed the confidential oracle for preventing the case from the malicious oracle by using below -sections. +Without confidential computing, the oracle operators(human) could see the content of sensitive data. +For example, if the oracle software stores important sensitive data to the disk or storage without sealing it, +it can be read by anyone who can access the disk or the storage. +So we developed the confidential oracle for preventing the case from the malicious oracle by using below sections. ### Technical Specification -For running the DEP oracle with confidential computing, we choose an Intel SGX which offers hardware-based memory -encryption for data security -using [Microsoft Azure Confidential Computing VM](https://learn.microsoft.com/en-us/azure/confidential-computing/overview). -Also, we choose an [EGo](https://www.edgeless.systems/products/ego/) SDK which enables to develop confidential apps +For confidential computing environment, we chose Intel SGX, which offers hardware-based memory +encryption for data security, using [Microsoft Azure Confidential Computing VM](https://learn.microsoft.com/en-us/azure/confidential-computing/overview). +Also, we chose [EGo](https://www.edgeless.systems/products/ego/) SDK, which enables the development of confidential apps written in Go language. ### Oracle Key -An oracle key is an asymmetric key that should be shared across all oracles. The request from provider and consumer that -oracle receive must be encrypted by the oracle public key. If the secure data encryption and decryption need to be -performed, the corresponding oracle private must be held by every oracle securely. How the all oracle shared the oracle -private key and how they stored the key securely will be described in next section. +The oracle key is an asymmetric key that should be shared across all oracles. The request from a data provider and a data consumer that +an oracle receives must be encrypted by the oracle public key. If the secure data encryption and decryption need to be +performed, the corresponding the oracle private key must be held by every oracle securely. How all oracles share the oracle +private key and how they store this key securely will be described in the next section. ### Oracle Key Handshake -The oracle private key is sealed by unique ID which is for the Intel SGX enclaves. If the oracle operator modified the -source code of the oracle, the unique ID will be changed. If the malicious oracle operator modified the source code of -the oracle to print logs of sensitive data or to leak a contents somewhere else, it would cause the serious privacy -problems. It means that the all oracle operators must use the only genuine binary built by selected code. -The only genuine binary can unseal the data in the SGX secure enclave. +The oracle private key is sealed by a unique ID, which is derived from the Intel SGX enclave. +If an oracle operator modifies the source code of the oracle, this unique ID will be changed. +If a malicious oracle operator modifies the source code of the oracle to print logs of sensitive data or to leak the data to somewhere else, it could cause a serious privacy problems. + +This means that the all oracle operators must only use the genuine binary built by selected code. +Only the genuine binary can unseal the data in the SGX secure enclave. +"Rewrite this section" If the oracle wants to register, it must use remote report composed of the promised security version and unique ID. So the one of the oracle approves the registration if the new oracle's remote report is valid. If you want a register the oracle, you can verify remote report that is valid or not using From be7f0b3f389fbe1b8dbb96789f6d4a47979c2346 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 08:55:43 +0900 Subject: [PATCH 75/84] Update 1-oracle-installation.md --- .../1-operate-oracle-nodes/1-oracle-installation.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md b/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md index ef52558a..43a95946 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/1-oracle-installation.md @@ -3,17 +3,17 @@ ## Hardware Requirement The oracle only works on [SGX](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/overview.html)-[FLC](https://github.com/intel/linux-sgx/blob/master/psw/ae/ref_le/ref_le.md) environment with a [quote provider](https://docs.edgeless.systems/ego/#/reference/attest) installed. -You can check if your hardware supports SGX, and it is enabled in the BIOS by following [EGo guide](https://docs.edgeless.systems/ego/#/getting-started/troubleshoot?id=hardware). +You can check if your hardware supports SGX and is enabled in the BIOS by following [EGo guide](https://docs.edgeless.systems/ego/#/getting-started/troubleshoot?id=hardware). ## Installation: Use Docker ### Pull an image -You can pull docker image by following CLI: +You can pull a docker image by following CLI: ```bash docker pull ghcr.io/medibloc/panacea-oracle:latest ``` It is highly recommended to use a specific Docker image tag instead of `latest`. -You can find image tags from the [GitHub Packages page](https://github.com/medibloc/panacea-oracle/pkgs/container/panacea-oracle). +You can find the image tags from the [GitHub Packages page](https://github.com/medibloc/panacea-oracle/pkgs/container/panacea-oracle). ### Run a container using SGX This is a sample command to show you how to run a container using SGX in your host. @@ -25,7 +25,7 @@ docker run \ ghcr.io/medibloc/panacea-oracle:latest \ ego run /usr/bin/oracled --help ``` -After successful installation, go to the process of [initializing oracle](5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md). +After a successful installation, go to the process of [initializing oracle](5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md). ### How about building from source? @@ -33,9 +33,9 @@ After successful installation, go to the process of [initializing oracle](5-orac You can build from source by referring to the following [installation-from-source](https://github.com/medibloc/panacea-oracle/blob/main/docs/installation-src.md). However, we highly recommend installing using docker. -This is because the uniqueID in `EGo` is sensitively changes depending on the Go dependency or local debug environment. +This is because the uniqueID in `EGo` is sensitive to changes on the Go dependency or local debug environment. -Therefore, it is recommended that you check the uniqueID with following CLI when you want to use the binary you built yourself. +You should check the uniqueID with following CLI when you want to use the binary you built yourself. ```bash ego sign ${enclave-json-path} # docker image use enclave in <project-dir>/scripts/enclave-prod.json ego uniqueid ${oracle-binary-path} From 19db378d46671b8b6077894b8126c179dfbf464f Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:41:00 +0900 Subject: [PATCH 76/84] Update 2-oracle-intialization.md --- .../2-oracle-intialization.md | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md b/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md index dc248739..2fc8c956 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/2-oracle-intialization.md @@ -1,12 +1,12 @@ # Oracle Initialization -#### Before run the oracle, you should initialize the oracle configuration. +#### Before running the oracle, you should initialize the oracle configuration. ## Preparations Before initializing the oracle, you should install the oracle described in [oracle-installation](./1-oracle-installation.md). -After install the oracle, create an empty directory on your host, to be mounted as the `/home_mnt` directory in the +After installing the oracle, create an empty directory on your host, to be mounted as the `/home_mnt` directory in the enclave. ```bash @@ -27,9 +27,9 @@ export ORACLE_CMD="docker run --rm \ $ORACLE_CMD init --home /home_mnt/.oracle ``` -When run the above CLI for initializing the oracle, the `config.toml` file will be generated under +When running the above CLI for initializing the oracle, the `config.toml` file will be generated under the `<directory-you-want>/.oracle` in the enclave. -The default `config.toml` file will be shown like this: +The default `config.toml` file will look like below. ```toml # This is a TOML config file. @@ -96,34 +96,34 @@ read-timeout = "15" #### Base Configuration -In `Base Configuration`, you need to configure a `oracle-mnemonic`, `oracle-acc-num`, and `oracle-acc-index`. Those -components should be corresponded to account that you registered in the Panacea. +In `Base Configuration`, you need to configure `oracle-mnemonic`, `oracle-acc-num`, and `oracle-acc-index`. These +components should correspond to the account that you registered in Panacea. #### Panacea Configuration -In `Panacea Configuration`, you need to configure a chain ID of Panacea. If you want to join the oracle to Panacea +In `Panacea Configuration`, you need to configure the chain ID of Panacea. If you want to join as an oracle to Panacea mainnet or testnet, please check the chain IDs in [mainnet-repoistory](https://github.com/medibloc/panacea-mainnet#intro) or [testnet-repository](https://github.com/medibloc/panacea-testnet#intro), respectively. -The default `grpc-addr` and `rpc-addr` setting is based on localnet. So if you want to connect with the Panacea -mainnet, the `grpc-addr` will be `https://grpc.gopanacea.org` and the `rpc-addr` will be `https://rpc.gopanacea.org`. +The default `grpc-addr` and `rpc-addr` setting is based on the localnet. So if you want to connect with Panacea +mainnet, the `grpc-addr` should be `https://grpc.gopanacea.org` and the `rpc-addr` should be `https://rpc.gopanacea.org`. Also, the `light-client-primary-addr` and `light-client-witness-addrs` are as same as `rpc-addr`, if you want to -connect with the Panacea mainnet. +connect with Panacea mainnet. -The `default-gas-limit` and `default-fee-amount` are set as `400000` and `2000000umed`, since the remote report has a -large bytes for oracle registration and oracle upgrade. So if you have finished an oracle registration or upgrade, you -could set a lower gas limit and fee amount than default setting. +The `default-gas-limit` and `default-fee-amount` are set as `400000` and `2000000umed`, since the remote report has +large bytes for oracle registration and oracle upgrade. Once you finish an oracle registration or an upgrade, you +could set a lower gas limit and fee amount than the default setting. #### IPFS Configuration -The oracle will use a public IPFS node for now. If you want to run a local IPFS node, the `ipfs-node-addr` is as same as -default setting. Also, you need to check that the IPFS gateway and the oracle `listen-addr` are at same port. You can -change the IPFS gateway in `$HOME/.ipfs/config`. If you want to know about RPC API of the IPFS, please refer +The oracle will use a public IPFS node for now. If you want to run a local IPFS node, the `ipfs-node-addr` is same as +default setting. Also, you need to check that the IPFS gateway and the oracle `listen-addr` are at the same port. You can +change the IPFS gateway in `$HOME/.ipfs/config`. If you want to know more about RPC API of the IPFS, please refer the [IPFS documentation](https://docs.ipfs.tech/reference/kubo/rpc/). ## Next -If you have done the oracle initialization, you could register oracle based on above configuration. If you want to know -how to register oracle, please refer the [oracle-registration](./4-oracle-registration.md) documentation. +If you have done the oracle initialization, you could register the oracle based on above configuration. If you want to know +how to register oracle, please refer to the [oracle-registration](./4-oracle-registration.md) documentation. From 66883c87d13f960ca76e7990afb077005df45429 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 10:36:22 +0900 Subject: [PATCH 77/84] Update 3-genesis-oracle.md --- .../3-genesis-oracle.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md b/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md index d29d21a7..7e2dbc00 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/3-genesis-oracle.md @@ -9,6 +9,7 @@ - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - Inchul Song <icsong@medibloc.org> + - Tae Jin Yoon(tj@medibloc.org) ## Synopsis @@ -41,7 +42,7 @@ EGo v1.0.1 (e1e48c9dbfdfd3cb2f2fda7602729162c9f762cc) ### Genesis Oracle Registration in Panacea -After uniqueID extraction is completed, the genesis oracle must be registered in `genesis.json` of Panacea. +After the uniqueID extraction is completed, the genesis oracle must be registered in `genesis.json` of Panacea. We provide a CLI for this process. ``` @@ -83,7 +84,7 @@ cat $HOME/.panacea/config/genesis.json | jq .app_state.oracle.oracles ``` ### Start block generation in Panacea -You need to launch the Panacea to start generating blocks. +You need to launch Panacea to start generating blocks. ```shell panacead start ``` @@ -91,16 +92,16 @@ panacead start ## Oracle Key Pair and Remote Report The genesis oracle must create an oracle private key and public key to use for data encryption/decryption. -The oracle also issues a remote report to allow others to prove that the genesis oracle is running inside secure enclave and the oracle key pair is generated inside the enclave. +This oracle also issues a remote report to allow others to prove that the genesis oracle is running inside secure enclave and the oracle key pair is generated inside the enclave. ### Generates oracle key pair and remote report in oracle + The genesis oracle needs to generate an oracle key pair and a remote report. -However, before generating oracle keys and remote reports, you need to know trusted block information from Panacea. +However, before generating the oracle keys and remote reports, the genesis oracle needs to know the trusted block information from Panacea +even though this information is not a necessary component of the oracle key pair generation or the remote report generation. +This information is not a necessary component because the two generation processes do not retrieve data from Panacea. -In fact, the genesis oracle does not need trusted block information for this process. -The reason is that oracle key pair and remote report generation process do not retrieve data from Panacea. -However, when the oracle participates in the verification operation (`oracled start`), the oracle needs to use a light client as it will retrieve data from Panacea. -Therefore, unless trusted block information is received during the process of generating an oracle key, the genesis oracle has no way to retrieve this block information. +When the oracle participates in the verification operation (`oracled start`), the oracle needs to use a light client as it will retrieve data from Panacea. Therefore, unless trusted block information is received during the process of generating an oracle key, the genesis oracle has no way to retrieve this block information; this is why we retrieve the trusted block information during the oracle key pair and remote report generation. You can get trusted block information by: ```shell @@ -213,4 +214,4 @@ params: When all these processes are completed, the genesis oracle can operate normally. -Next, see [Running node](./5-running-node.md) where you can run the genesis oracle. \ No newline at end of file +Next, see [Running node](./5-running-node.md) where you can run the genesis oracle. From 1e7582267d7c617dc73390578130a2f94452115d Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 10:57:48 +0900 Subject: [PATCH 78/84] Update 4-oracle-registration.md --- .../4-oracle-registration.md | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md b/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md index d67635cf..0b05a151 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/4-oracle-registration.md @@ -4,7 +4,7 @@ This document is an instruction to register an oracle to Panacea ## Get Trusted Block Information -To request oracle registration to Panacea, trusted block information (height and hash), which will be used for [light client](), is required and need to be verified by other registered oracle. +To request an oracle registration to Panacea, trusted block information (height and hash), which will be used for [light client](), is required and need to be verified by other registered oracle. You can get trusted block information by: ```bash @@ -14,11 +14,11 @@ HEIGHT=$(echo $BLOCK | jq -r .block.header.height) HASH=$(echo $BLOCK | jq -r .block_id.hash) ``` -If you need more information about public RPC endpoints provided by MediBloc team, you can refer [this](https://github.com/medibloc/panacea-mainnet#public-endpoints) +If you need more information about public RPC endpoints provided by MediBloc team, you can refer to [this](https://github.com/medibloc/panacea-mainnet#public-endpoints) ## Request to Register Oracle -In addition to the trusted block information, the following arguments are also required in oracle registration. +In addition to the trusted block information, the following arguments are also required in the oracle registration. | Argument | requirement | Description | |-----------------------------------|-------------|------------------------------------------------------------------------------------------------------| @@ -45,12 +45,12 @@ docker run \ ``` Then, a new key pair, called `Node Key`, and its remote report will be generated. -The `Node Key` is used to be shared the oracle private key. +The `Node Key` is used to transfer the oracle private key securely. Since the oracle private key must be shared in a very secure way, the key will be encrypted with the public key of the `Node Key` so that only the oracle can decrypt it. {% hint style="danger" %} -The private key of `Node Key` is also stored in secure way as a sealed file, named `node_priv_key.sealed` in default. -This `node_priv_key.sealed` file is the only clue to decrypt the encrypted oracle private key, we recommend to manage it very carefully in case that you need to restore the oracle private key again later. +The private key of `Node Key` is also stored in a secure way as a sealed file, named `node_priv_key.sealed` in default. +This `node_priv_key.sealed` file is the only clue to decrypt the encrypted oracle private key, and, hence, we highly recommend you to manage it very carefully in case you need to restore the oracle private key again later. {% endhint %} If you have tried to request `register-oracle` before, previously generated `node_priv_key.sealed` would exist. @@ -66,30 +66,31 @@ Or, we recommend to back up the existing `node_priv_key.sealed` file. ## Subscribe Approval of Registration -If the transaction for request of oracle registration succeeds, oracle will start to subscribe `ApproveOracleRegistrationEvent`. -Other oracles already registered will do some verifications of this registration by checking if: +If the transaction for requesting oracle registration succeeds, the newly registered oracle will start subscribing to `ApproveOracleRegistrationEvent`. +Other oracles that are already registered will do some verifications of this registration by checking if: - correct version of oracle binary is used - the oracle is running inside an enclave - the `Node Key` is generated inside the enclave - the trusted block information is valid When the registration is verified successfully, other oracles will send a transaction for approval of the oracle registration. -The oracle would detect the approval, and then the oracle start to retrieve the oracle private key. -As a result of retrieval of oracle private key, a sealed file named `oracle_priv_key.sealed` (default file name) will be generated. -Using the sealed oracle private key, this oracle is now ready to perform tasks such as verifying data or other oracles. +Since the oracle is already subscribing to the event, it will detect the approval, and then retrieve the oracle private key. +As a result of the oracle private key retrieval, a sealed file named `oracle_priv_key.sealed` (default file name) will be generated. +Using this sealed oracle private key, the oracle is now ready to perform tasks such as verifying data or other oracles. + For more information about what oracle does, please refer the [running an oracle node](5-running-node#what-oracle-does.md). {% hint style="danger" %} Like `node_priv_key.sealed`, `oracle_priv_key.sealed` is also very important for working as a valid oracle. -Thus, we highly recommend to manage the `oracle_priv_key.sealed` file very carefully. -In case that operator lost the `oracle_priv_key.sealed` file for any reason, it can be retrieved again using `get-oracle-key` CLI with the `node_priv_key.sealed` file, which is generated when request oracle registration above. +Thus, we highly recommend you to manage the `oracle_priv_key.sealed` file very carefully. +In case an operator loses the `oracle_priv_key.sealed` file for any reason, it can be retrieved again using `get-oracle-key` CLI with the `node_priv_key.sealed` file, which is generated when oracle registration is requested as above. {% endhint %} ## Manually Retrieve Oracle Private Key -For any reasons, the oracle can stop before the oracle private key is retrieved. +Because of any unforseen reasons, the oracle could stop before the oracle private key is retrieved. In this case, you can also retrieve the oracle private key through `get-oracle-key` CLI. -If at least one registered oracle approves the registration, this will be able to retrieve the oracle private key successfully. +If at least one registered oracle approves this registration, you will be able to retrieve the oracle private key successfully. ```bash docker run \ @@ -106,6 +107,6 @@ You can check the status of your registration with the uniqueID and oracle addre panacead q oracle oracle-registration <unique-id> <oracle-address> ``` -If at least one oracle approved this registration, the `encrypted_oracle_priv_key` will have some value. +If at least one oracle approves this registration, the `encrypted_oracle_priv_key` will not be empty. -Now, you are ready to run your own oracle. Please refer the [running a node](./5-running-node.md) instructions. \ No newline at end of file +Now, you are ready to run your own oracle. Please refer the [running a node](./5-running-node.md) instructions. From 342abaa7c491014fc4539643722e7df8a7d4d688 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 11:18:55 +0900 Subject: [PATCH 79/84] Update and rename 5-running-node.md to 5-running-oracle-node.md --- ...nning-node.md => 5-running-oracle-node.md} | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) rename .gitbook/5-oracles/1-operate-oracle-nodes/{5-running-node.md => 5-running-oracle-node.md} (56%) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md b/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md similarity index 56% rename from .gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md rename to .gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md index 080b13dc..ac4869fc 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-node.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md @@ -1,10 +1,12 @@ -# Running a Node +# Running an Oracle Node ## Overview -If you have completed the previous steps, now is the step to actually run oracle. +If you have completed previous steps, now is the time to actually run oracle. + +The oracle is responsible for validating the data provider's data and +ensuring that the data is transmitted to the data consumer securely using the `oracle key`. -The oracle is responsible for validating the provider's data and ensuring that the data is transmitted securely using the `oracle key`. In this process, oracle operators can earn commissions according to the commission rate registered to Panacea. The oracle also serves to validate and approve `registration/upgrade` requests from other oracles. @@ -18,7 +20,7 @@ You can see the details in [What oracle does](#what-oracle-does). ## Start oracle -You can start oracle with following CLI: +You can start an oracle with the following CLI: ```bash docker run \ --device /dev/sgx_enclave \ @@ -27,7 +29,7 @@ docker run \ ghcr.io/medibloc/panacea-oracle:latest \ ego run /usr/bin/oracled start ``` -If oracle start is successful, you can see the following log message like example below: +If the oracle is successful started, you will see the following log message: ``` EGo v1.1.0 (4625a610928f4f4b1ea49262c363376b1e574b6c) [erthost] loading enclave ... @@ -45,44 +47,44 @@ time="2023-01-11T07:40:31Z" level=info msg="HTTP server is started: 127.0.0.1:80 ### Validate provider data & issue certificate -Oracle provides a REST API to validate data from a provider and issue a certificate. +Oracle provides a REST API to validate data provided by a data provider and issue a certificate. -Validation procedure is as follows: -1. Check the address of the requested provider with JWT -2. Check the status of related `deal` -3. Decrypt provider's encrypted data & check data hash and data schema +The validation procedure is as follows: +1. Check the address of the data provider who is requesting data validation with JWT +2. Check the status of the related `deal` +3. Decrypt the data provider's encrypted data & check the data hash and the data schema -If validation passes successfully, oracle issues a certificate as follows: +If the validation passes successfully, the oracle issues a certificate as follows: 1. Generate a `secret key` by combining `oracle private key`, deal ID, and data hash 2. Re-encrypt the data using the `secret key` and put it in `IPFS` 3. Issue a certificate with `oracle private key` signature -Providers will be able to submit consent to Panacea with the issued certificate. +Data providers will be able to submit a consent to Panacea with the issued certificate. Panacea ensures that a commission is paid to the oracle operator who issued the certificate when the data delivery is successfully completed. -### Safely transmit provider data accessibility to consumer +### Safely transmit the data accessibility to the data consumer -Oracle provides a REST API to get data accessibility to consumer. +Oracle provides a REST API to get data accessibility to the data consumer. -After the `submit-consent` transaction succeeds in Panacea, oracle transmits secret key that enables data access to the consumer. +After the `submit-consent` transaction succeeds in Panacea, the oracle transmits a secret key that enables data access to the data consumer. The detailed process is as follows: -1. Check the address of the requested consumer with JWT -2. Check if the requested consumer is the owner of the `deal` -3. Check if the `submit-consent` transaction succeeds +1. Check the address of the data consumer who is requesting data access with JWT +2. Check if the requesting consumer is the owner of the `deal` +3. Check if the `submit-consent` transaction is present and successful 4. Make `encrypted secret key` using `consumer public key` -5. Response with `encrypted secret key` to consumer +5. Respond with `encrypted secret key` to the data consumer -Consumer can obtain the `secret key` through his/her `private key`, and can decrypt data from `IPFS`. +The data consumer can obtain the `secret key` through his/her `private key`, and can decrypt data from `IPFS`. ### Validate and approve registration/upgrade requests of other oracles -Oracle subscribes `registration/upgrade` events from Panacea. +The oracle subscribes to `registration/upgrade` events from Panacea. -When another oracle sends a `registration/upgrade`, the running oracle do some verifications by checking if: -- correct version of oracle binary is used +When another oracle sends a `registration/upgrade`, the running oracle do verifications by checking if: +- a correct version of the oracle binary is used - the oracle is running inside an enclave - the `Node Key` is generated inside the enclave - the trusted block information is valid - the oracle is registered (at upgrade requests) -When the `registration/upgrade` is verified successfully, oracle send a transaction for approval of the oracle `registration/upgrade`. \ No newline at end of file +When the `registration/upgrade` is verified successfully, the racle send a transaction for approval of the oracle `registration/upgrade`. From ed0f9964a71116ae5628f47e59e68f368c35851c Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 11:22:33 +0900 Subject: [PATCH 80/84] Update 6-update-oracle-info.md --- .../1-operate-oracle-nodes/6-update-oracle-info.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md b/.gitbook/5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md index ad49a14f..99556a02 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/6-update-oracle-info.md @@ -4,7 +4,7 @@ This document outlines how to edit the oracle information (endpoint and commissi ## Command Line for Updating -Using the below CLI, you can update your endpoint and/or commission rate +Using below CLI, you can update your endpoint and/or commission rate ```bash docker run \ @@ -22,13 +22,13 @@ docker run \ | endpoint | optional | The endpoint of oracle | | oracle-commission-rate | optional | The oracle commission rate. | -As you can see above table, both flags are optional. -You can enter the flags you want to change. +As you can see from above table, both flags are optional. +You can choose and enter only the flags you want to change. It is noted that the oracle commission rate cannot be greater than oracle max change rate. And once changed, the oracle commission rate cannot be changed within the next 24 hours. -You can confirm the changes you made if the transaction succeeds +You can confirm the changes you made when the transaction succeeds ```bash panacead q oracle oracle <your-oracle-address> -``` \ No newline at end of file +``` From 7afe97eed545a67c7eb2976101d2da45f8c75f9d Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 13:42:07 +0900 Subject: [PATCH 81/84] Update 7-oracle-upgrade.md --- .../7-oracle-upgrade.md | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md b/.gitbook/5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md index 20c9be09..cbb02324 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/7-oracle-upgrade.md @@ -1,12 +1,12 @@ # Oracle Upgrade -This document is about the whole process of oracle upgrade. +This document is about the entire process of oracle upgrade. ## Oracle Upgrade Process -All oracles registered in Panacea are forced to run oracle with the same unique ID stored in the oracle module. -Since the new version (to be upgraded) of oracle will have a unique ID different from the existing one, the new unique ID should be registered in Panacea. -This process is determined by on-chain governance, thus upgrade can be proposed by an `oracle-upgrade` proposal. +All oracles registered in Panacea are forced to run the oracle with the same unique ID stored in the oracle module. +Since the new version (to be upgraded) of oracle will have a unique ID different from the existing one, a new unique ID should be registered in Panacea. +This process is determined by on-chain governance; thus, an upgrade can be proposed by an `oracle-upgrade` proposal. ### Submit Proposal for Oracle Upgrade @@ -25,9 +25,9 @@ panacead tx gov submit-proposal oracle-upgrade \ ``` - title: The title of oracle upgrade proposal -- description: The description of oracle upgrade proposal -- upgrade-height: Target height to be upgraded -- upgrade-unique-id: Unique ID of oracle to be upgraded +- description: A description of oracle upgrade proposal +- upgrade-height: A target height to be upgraded +- upgrade-unique-id: The unique ID of oracle to be upgraded - deposit: A deposit for proposal If the proposal passes, you can check the oracle upgrade information with the below CLI. @@ -39,8 +39,8 @@ panacead q oracle oracle-upgrade-info ### Upgrade Oracle Node {% hint style="info" %} -You can upgrade oracle any time after an `oracle-upgrade` proposal has passed (even before the upgrade target height is reached). -However, since the new version of oracle can be active after the target height, the current version of oracle must be run before the target height. +You can upgrade your oracle any time after an `oracle-upgrade` proposal has passed (even before the upgrade target height is reached). +However, since the new version of oracle can be active after the target height, the current version of oracle must be running before the target height. You do not have to stop the old version of oracle when upgrading to a new version of oracle. You can run different versions of oracle at the same time using the `home` flag. @@ -48,10 +48,11 @@ You can run different versions of oracle at the same time using the `home` flag. #### Initialization -The `oracle_priv_key.sealed` used in the previous version cannot be used in the new version of oracle. -(Because it cannot be decrypted in the new version of oracle. For more info, refer to [this](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md)) -Therefore, the new version of oracle should also be shared the oracle private key. -This is very similar to the process of registering oracle. +The `oracle_priv_key.sealed` used in the previous version cannot be used in the new version of oracle because it cannot be decrypted in the new version of oracle. For more info, refer to [this](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md) + +Therefore, the new version of oracle should also know the oracle private key. +The oracle can retrieve the oracle private key with a similar process to registering an oracle. + Let's start with [initialization](2-oracle-intialization.md) of the new version of oracle. ```bash @@ -70,7 +71,7 @@ After initialization, complete the configuration by referring to the [Configurin #### Request to Upgrade Oracle -The purpose of this request is to securely be shared the oracle private key for a new version of oracle. +The purpose of this request is to securely receive the oracle private key for a new version of oracle. It is similar to sharing the oracle private key in [oracle registration](4-oracle-registration#request-to-register-oracle.md). Prior to the request, trusted block information is also required. You can get trusted block information with the following command: @@ -97,8 +98,8 @@ This `node_priv_key.sealed` file is also necessary to retrieve the oracle privat #### Subscribe Approval of Upgrade -If the transaction for `upgrade-oracle` succeeds, oracle will start subscribing to the `ApproveOracleUpgradeEvent`. -Upon approval by other oracles, this new version of oracle can be shared the oracle private key. +If the transaction for `upgrade-oracle` succeeds, the oracle will start subscribing to the `ApproveOracleUpgradeEvent`. +Upon approval by other oracles, this new version of oracle can retrieve the oracle private key. This process is similar to [oracle-registration](4-oracle-registration#subscribe-approval-of-registration.md), so please refer it for details. #### Running the Upgraded Oracle @@ -109,4 +110,4 @@ After reaching the target height of the upgrade, you can start the new version o $ORACLE_CMD start --home /home_mnt/.oracle-new ``` -See [running-oracle](5-running-node.md) for more information. \ No newline at end of file +See [running-oracle](5-running-node.md) for more information. From 769e1b80c35538e4c9bec7435f278d805a79a427 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 13:47:26 +0900 Subject: [PATCH 82/84] Update 8-verify-remote-report.md --- .../8-verify-remote-report.md | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/8-verify-remote-report.md b/.gitbook/5-oracles/1-operate-oracle-nodes/8-verify-remote-report.md index c7717ad4..44df05da 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/8-verify-remote-report.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/8-verify-remote-report.md @@ -11,26 +11,30 @@ - Hansol Lee <hansol@medibloc.org> - Myongsik Gong <myongsik_gong@medibloc.org> - Inchul Song <icsong@medibloc.org> + - Tae Jin Yoon <tj@medibloc.org> ## Synopsis -This document describes how to validate remote reports generated by Oracle. +This document describes how to validate remote reports generated by an oracle. ## Remote Report -Remote reports are one of the core of our protocol. This remote report must be submitted when the genesis oracle or new oracle participant registers to Panacea. A remote report can verify that the genesis oracle or new oracle participant is the correct oracle. +Remote reports are one of the core elements of this protocol. This remote report must be submitted when the genesis oracle or a new oracle participant registers to Panacea. A remote report can verify that the genesis oracle or a new oracle participant is the correct oracle. -The correct oracle means an oracle with a unique ID agreed upon in Panacea. -If the unique ID changed, it can be determined that it is an invalid oracle. See the [oracle-key-handshake](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md#oracle-key-handshake) documentation for details on this. +The correct oracle means the oracle with a unique ID agreed upon in Panacea. +If the unique ID is different, it can be determined that one is an invalid oracle. +See [oracle-key-handshake](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md#oracle-key-handshake) documentation for details on this. - For the remote report generated by the genesis oracle, you can see [genesis oracle](./3-genesis-oracle.md) section. -- For the remote report generated by the new oracle registration, you can see [oracle registration](./4-oracle-registration.md) section. -- How to verify correct oracle via remote report, you can see [confidential oracle](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md) section. +- For the remote report generated by a new oracle registration, you can see [oracle registration](./4-oracle-registration.md) section. +- On how to verify correct oracle via remote report, you can see [confidential oracle](../../3-protocol-devs/1-dep-specs/5-confidential-oracle.md) section. ### Validation a genesis oracle -To verify the genesis oracle, you need an oracle public key and a remote report generated based on that oracle public key. This information can be obtained from Panacea's oracle module parameters. +To verify the genesis oracle, you need the oracle public key and a remote report generated based on the oracle public key. +This information can be obtained from Panacea's oracle module parameters. + You need to create `public_key_info.json` file through the process below. ```shell ORACLE_PUBLIC=$(panacead q oracle params --node <node-rpc-address> -o json) @@ -65,7 +69,7 @@ docker run \ time="2023-01-12T01:45:45Z" level=info msg="remote report is verified successfully" ``` -### Validation a new oracle registration +### Validation on a new oracle registration To verify a newly registered oracle, the public key of the node registered by this oracle and the remote report are required. This information can be found in oracle registration store on Panacea. @@ -92,4 +96,4 @@ docker run \ **Output** ```shell time="2023-01-12T01:45:45Z" level=info msg="remote report is verified successfully" -``` \ No newline at end of file +``` From 143903311be220350086cfbae455f3d08117219d Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 14:45:57 +0900 Subject: [PATCH 83/84] Update .gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md Co-authored-by: audtlr24 <audtlr24@gmail.com> --- .../5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md b/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md index ac4869fc..34a1ca07 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md @@ -87,4 +87,4 @@ When another oracle sends a `registration/upgrade`, the running oracle do verifi - the trusted block information is valid - the oracle is registered (at upgrade requests) -When the `registration/upgrade` is verified successfully, the racle send a transaction for approval of the oracle `registration/upgrade`. +When the `registration/upgrade` is verified successfully, the oracle send a transaction for approval of the oracle `registration/upgrade`. From 8d8c3d25031f19a914a1108c58795471f9dae8e6 Mon Sep 17 00:00:00 2001 From: tjyoon0324 <102934148+tjyoon0324@users.noreply.github.com> Date: Fri, 20 Jan 2023 14:47:12 +0900 Subject: [PATCH 84/84] Update 5-running-oracle-node.md --- .../5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md b/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md index 34a1ca07..5fbd3c1e 100644 --- a/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md +++ b/.gitbook/5-oracles/1-operate-oracle-nodes/5-running-oracle-node.md @@ -87,4 +87,4 @@ When another oracle sends a `registration/upgrade`, the running oracle do verifi - the trusted block information is valid - the oracle is registered (at upgrade requests) -When the `registration/upgrade` is verified successfully, the oracle send a transaction for approval of the oracle `registration/upgrade`. +When the `registration/upgrade` is verified successfully, the oracle sends a transaction for approval of the oracle `registration/upgrade`.