Skip to content

Commit

Permalink
Merge branch 'master' into bugfix/nodejs
Browse files Browse the repository at this point in the history
  • Loading branch information
Artemkaaas authored Mar 13, 2019
2 parents bcb0e37 + 379e02a commit 503becb
Show file tree
Hide file tree
Showing 12 changed files with 3,723 additions and 171 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile.cd
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def testing() {
stage('Testing') {
parallel([
'ubuntu-test' : { ubuntuTesting() },
'redhat-test' : { rhelTesting() },
// FIXME 'redhat-test' : { rhelTesting() }, https://jira.hyperledger.org/browse/IS-1212
'android-test': { androidTesting() },
'windows-test': { windowsTesting() },
'ios-test' : { iosTesting() }
Expand Down
2 changes: 1 addition & 1 deletion Jenkinsfile.ci
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def testing() {
'android-test': { androidTesting() },
'macos-test' : { macosTesting() },
'ios-test' : { iosTesting() },
'redhat-test' : { rhelTesting() },
// FIXME 'redhat-test' : { rhelTesting() }, https://jira.hyperledger.org/browse/IS-1212
'windows-test': { windowsTesting() }
])
}
Expand Down
2 changes: 2 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Find the other Indy docs at https://hyperledger-indy.readthedocs.io
build-guides/index.rst
migration-guides/index.rst
architecture/index.rst
zh/indy-walkthrough-zh.md



.. toctree::
Expand Down
29 changes: 29 additions & 0 deletions docs/zh/indy-walkthrough-zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

# 什麼是 Indy 和 Libindy,還有為什麼它們那麼重要?

Indy 提供一個私密、安全、身份的生態系統,而Libindy 為它提供客戶端。Indy 使人 -- 而不是傳統機構 -- 控制他們的個人資料以及如何公開。它令各種創新變得可能:授權、嶄新的支付流程、資產及文件管理、不同形式的委託、聲譽累積、與其他新技術整合等等。

Indy使用開源的分佈賬戶技術。這個賬戶是由一群參與者合作建立的一種數據庫,而非一個中央管理的大規模數據庫。數據冗餘地存在於多個地方,而由多部參與的電腦(機器)的交易所構成,透過大而有力的加密標準加以保護。它的設計充分使用密鑰管理和網絡安全的最佳實踐模式。所得的結果是一個可靠、公共的信任源頭,不受單一個體所控制,系統堅實而不受人侵駭入,足以抵禦其他個體敵意的破壞和顛覆。

如果你對加密學概念和區塊鏈技術還有疑惑,不用害怕,這指南會給你介紹Indy的主要概念,你來對地方了。

## 我们要讨论什么?
我们的目标是向你介绍很多关于 Indy 的概念,帮助你来理解让这一起工作起来的背后的原因。

我们会将整个过程编为一个故事。Alice,一个虚构的 Faber 大学的毕业生,想要应聘一家虚构的公司 Acme Corp 的一份工作。当她获得了这份工作后,她想要向 Thrift 银行申请一笔贷款,这样她就可以购买一辆汽车了。在工作申请表单上,她想用她的大学成绩单作为受过教育证明,并且一旦被录用后,Alice 想使用被雇佣的事实来作为申请贷款的信誉凭证。

在当今的世界里,身份信息以及信任交互非常混乱,它们很慢,与隐私性相违背,容易受到欺诈。我们将会展示给你 Indy 是如何让这些产生了巨大的进步。

作为 Faber 大学的毕业生,Alice 收到了一封毕业生的 newsletter,从中了解到她的母校可以提供数字成绩单(digital transcripts)。她登录了学校的毕业生网站,通过点击 获得成绩单 按钮,她申请了自己的成绩单。(其他的发起这个请求的方式还可能包括扫描一个 QR code,从一个公共的 URL 下载一份打包的成绩单,等等)

## About Alice

Alice 还没有意识到,想要使用这个数字的成绩单,她需要一个新的类型的身份信息 - 并不是 Faber 大学存储在在校(on-campus)数据库中为她创建的传统的身份信息,而是一个属于她自己的全新的便携的身份信息,独立于所有的过去和将来的关系,不经过她的允许,没有人能够废除(revoke)、指派(co-opt)或者关联(correlate)这个身份信息。这就是一个 自我主权的身份信息(self-sovereign identity),也是 Indy 的核心功能。

在常规的情况下,管理一个自我主权的身份信息会要求使用 一个工具,比如一个桌面的或者手机的应用程序。它可能是一个独立的应用,或者使用一个第三方的服务机构(代理商)提供的账本服务。Sovrin 基金会(Sovrin Foundation)发布了一个这种类型的工具。Faber 大学了解了这些需求,并会建议 Alice 安装一个 Indy app 如果她没有安装过的话。这个 app 会作为点击 获得成绩单 按钮之后的工作流中的一部分而被安装。

在常规的情况下,管理一个自我主权的身份信息会要求使用 一个工具,比如一个桌面的或者手机的应用程序。它可能是一个独立的应用,或者使用一个第三方的服务机构(代理商)提供的账本服务。Sovrin 基金会(Sovrin Foundation)发布了一个这种类型的工具。Faber 大学了解了这些需求,并会建议 Alice 安装一个 Indy app 如果她没有安装过的话。这个 app 会作为点击 获得成绩单 按钮之后的工作流中的一部分而被安装。


当 Alice 点击了 获得成绩单 按钮后,她会下载一个带有一个 Indy 连接请求 的文件。这个连接请求文件的扩展名为 .indy,并且会和 Alice 的 Indy app 相关联,将会允许 Alice 创建跟另外一个在这个账本生态圈(ledger ecosystem)存在的一方(Faber 大学)的一个安全的信息沟通频道(channel)。

5 changes: 5 additions & 0 deletions vcx/wrappers/node/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"presets": [
"es2015"
]
}
48 changes: 47 additions & 1 deletion vcx/wrappers/node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,51 @@ npm install
npm ci
npm run doc-gen
```
* A directory will be created locally `./docs` which contains an `index.html` file which can be used to navigate the generated documents.
* A directory will be created locally `./docs` which contains an `index.html` file which can be used to navigate the
generated documents.

## Run Demo
- The demo represents example how 2 actors, **Alice** and **Faber** institution, exchange credentials.
- They consult may consult Indy blockchain (pool of Indy nodes) to find out certain pieces of information. **Faber**
and **Alice** are represented by 2 scripts `faber.js` and `alice.js` but you could imagine that there's a webserver
running code alike what's inside `faber.js` and there's a perhaps smartphone or laptop running code
alike iin `alice.js`.
- **Faber** and **Alice** in the demo also don't exchange the credentials peer to peer. Instead, the exchange happens
through intermediary service represented by **Dummy Cloud Agent**. The data **Alice** and **Faber** are exchanging over
**Dummy Cloud Agent** are however encrypted and cannot be read by the **Dummy Cloud Agent**. The **Dummy Cloud Agent**
is something like illiterate postman. He'll take a letter from one party and delivers it to the other party. But he's
unable to read the messages he's handling.


### Pre-requirements
##### Libraries
Before you'll be able to run demo, you need to make sure you've compiled
[`libindy`](https://github.com/hyperledger/indy-sdk/tree/master/libindy),
[`libvcx`](https://github.com/hyperledger/indy-sdk/tree/master/vcx) and
[`libnullpay`](https://github.com/hyperledger/indy-sdk/tree/master/libnullpay) libraries and are available on your
system.
#### Indy pool
You'll also have to run pool of Indy nodes on your machine. You can achieve by simply running a docker container
which encapsulates multiple interconnected Indy nodes.
[Instructions here](https://github.com/hyperledger/indy-sdk#how-to-start-local-nodes-pool-with-docker).

### Steps to run demo
- Install NodeJS dependencies
```
npm install
```

- Compile LibVCX Wrapper
```
npm compile
```
- Start [Dummy Cloud Agent](../../dummy-cloud-agent)
- Run Faber agent, representing an institution
```
npm run demo:faber
```
- Give it a few seconds, then run Alice's agent which will connect with Faber's agent
```
npm run demo:alice
```

86 changes: 86 additions & 0 deletions vcx/wrappers/node/demo/alice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import {DisclosedProof} from "../dist/src/api/disclosed-proof";
import {Connection} from "../dist/src/api/connection";
import {Credential} from "../dist/src/api/credential";
import {StateType} from "../dist/src";
import readlineSync from 'readline-sync'
import sleepPromise from 'sleep-promise'
import * as demoCommon from './common'

const provisionConfig = {
'agency_url': 'http://localhost:8080',
'agency_did': 'VsKV7grR1BUE29mG2Fm2kX',
'agency_verkey': 'Hezce2UWMZ3wUhVkh2LfKSs8nDzWwzs2Win7EzNN3YaR',
'wallet_name': 'alice_wallet',
'wallet_key': '123',
'payment_method': 'null',
'enterprise_seed': '000000000000000000000000Trustee1'
};

const logLevel = 'warn';

async function run() {
await demoCommon.initLibNullPay();

console.log("#0 initialize rust API from NodeJS");
await demoCommon.initRustApiAndLogger(logLevel);

console.log("#1 Provision an agent and wallet, get back configuration details");
let config = await demoCommon.provisionAgentInAgency(provisionConfig);

console.log("#2 Initialize libvcx with new configuration");
await demoCommon.initVcxWithProvisionedAgentConfig(config);

console.log("#9 Input faber.py invitation details");
const details = readlineSync.question('Enter your invite details: ');
const jdetails = JSON.parse(details);

console.log("#10 Convert to valid json and string and create a connection to faber");
const connection_to_faber = await Connection.createWithInvite({id: 'faber', invite: JSON.stringify(jdetails)});
await connection_to_faber.connect({data: '{"use_public_did": true}'});
await connection_to_faber.updateState();

console.log("#11 Wait for faber.py to issue a credential offer");
await sleepPromise(5000);
const offers = await Credential.getOffers(connection_to_faber);
console.log(`Alice found following credentiaal offers: ${JSON.stringify(offers)}`);

// Create a credential object from the credential offer
const credential = await Credential.create({sourceId: 'credential', offer: JSON.stringify(offers[0])});

console.log("#15 After receiving credential offer, send credential request");
await credential.sendRequest({connection: connection_to_faber, payment : 0});

console.log("#16 Poll agency and accept credential offer from faber");
let credential_state = await credential.getState();
while (credential_state !== StateType.Accepted) {
sleepPromise(2000);
await credential.updateState();
credential_state = await credential.getState();
}

console.log("#22 Poll agency for a proof request");
const requests = await DisclosedProof.getRequests(connection_to_faber);

console.log("#23 Create a Disclosed proof object from proof request");
const proof = await DisclosedProof.create({sourceId: 'proof', request: JSON.stringify(requests[0])});

console.log("#24 Query for credentials in the wallet that satisfy the proof request");
const credentials = await proof.getCredentials();

// Use the first available credentials to satisfy the proof request
for (let i = 0; i < Object.keys(credentials['attrs']).length; i++) {
const attr = Object.keys(credentials['attrs'])[i];
credentials['attrs'][attr] = {
'credential': credentials['attrs'][attr][0]
}
}

console.log("#25 Generate the proof");
await proof.generateProof({selectedCreds: credentials, selfAttestedAttrs: {}});

console.log("#26 Send the proof to faber");
await proof.sendProof(connection_to_faber);
}


run();
30 changes: 30 additions & 0 deletions vcx/wrappers/node/demo/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {initRustAPI, initVcxWithConfig, provisionAgent} from "./../dist/src";
import * as ffi from "ffi";
import 'fs';

export async function initLibNullPay() {
const myffi = ffi.Library('/usr/local/lib/libnullpay.dylib', {nullpay_init: ['void', []]});
await myffi.nullpay_init();
}

export async function initRustApiAndLogger(logLevel) {
let rustApi = initRustAPI();
await rustApi.vcx_set_default_logger(logLevel);
}

export async function provisionAgentInAgency(config) {
return JSON.parse(await provisionAgent(JSON.stringify(config)));
}

export async function initVcxWithProvisionedAgentConfig(config) {
config['institution_name'] = 'faber';
config['institution_logo_url'] = 'http://robohash.org/234';
config['genesis_path'] = `${__dirname}/docker.txn` ;
await initVcxWithConfig(JSON.stringify(config));
}

export function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}
4 changes: 4 additions & 0 deletions vcx/wrappers/node/demo/docker.txn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node1","blskey":"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba","blskey_pop":"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1","client_ip":"127.0.0.1","client_port":9702,"node_ip":"127.0.0.1","node_port":9701,"services":["VALIDATOR"]},"dest":"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv"},"metadata":{"from":"Th7MpTaRZVRYnPiabds81Y"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node2","blskey":"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk","blskey_pop":"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5","client_ip":"127.0.0.1","client_port":9704,"node_ip":"127.0.0.1","node_port":9703,"services":["VALIDATOR"]},"dest":"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb"},"metadata":{"from":"EbP4aYNeTHL6q385GuVpRV"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node3","blskey":"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5","blskey_pop":"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh","client_ip":"127.0.0.1","client_port":9706,"node_ip":"127.0.0.1","node_port":9705,"services":["VALIDATOR"]},"dest":"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya"},"metadata":{"from":"4cU41vWW82ArfxJxHkzXPG"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"127.0.0.1","client_port":9708,"node_ip":"127.0.0.1","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}
Loading

0 comments on commit 503becb

Please sign in to comment.