Compliance Server on stellar network
合同会社kumanoteの田中です。
引き続きstellarの実装調査を行いましたので、そのメモになります。
前回までの記事
- getting started stellar with javascript SDK - Qiita
- Let's become an anchor on stellar network - Qiita
- Federation Server on stellar network - Qiita
Compliance Serverとは
金融的なサービスの運営者は、社会的悪にその力を貸さないようにする義務があります。
マネーロンダリング、振込詐欺、脱税等に助力しないということです。
このため、サービス内では、誰が誰に対して送金しているかをチェックし、サービスがコンプライアンスを満たしているかをチェックする義務がでてきます。
この部分を切り出し、汎用的に利用できるようにしたものがCompliance Serverということになります。
BitcoinやEthereum上のサービスも当然こういう性質をもつべきなのですが、そこがないものが多いですよね。
それが魅力でもあり、規制対象でもあるのでしょうが。。。
規制が厳しくなる方向で世の中が動いていますが、確実にこういうサービスは需要がでてくると思います。
(各暗号通貨の)アドレスと個人情報(KYC)をあつめたデータベースを構築し、Complianceをチェックする機関がでてくるかもしれませんね。
こういうのも含めて、結局は送金手数料がかかってくるようになってしまいそうで・・面白くないですね。
まあ、世の中の流れはおいておいて、以下試した内容をかいつまんでご紹介します。
complianceの仕組みの流れ
compliance-protocolに準じるのが良いみたいです。
example of flow case a1 send some credit to b1
objects
- 自社システム: A(bankA.com)
- そのアカウント: a1
- 他者システム: B(bankB.com)
- そのアカウント: b1
flow
- b1を問い合わせる(Bのfederation)(送信するため)
- Aがhttps://bankB.com/.well-known/stellar.toml を参照し、BのFEDERATION_SERVERのendpointを取得する
- AがBのFEDERATION_SERVERに対し、b1の情報を取得するためのリクエストを投げる
- Aがb1のcomplianceチェックを委託する
- Aがhttps://bankB.com/.well-known/stellar.toml を参照し、BのAUTH_SERVERのendpointを取得する
- AがBのAUTH_SERVERに対して、a1の情報を送信する
- Bがcompliance(auth request)チェックを行う
- Bがリクエストのsender情報を元に、https://bankA.com/.well-known/stellar.toml を参照し、AのSIGNING_KEYを取得する
- Bがauth requestのキーチェックを行う。(ちゃんとAから送信されていること)
- Bがリクエストのsender情報を元に、senderのcomplianceチェックを行う
- Bが以下の情報を元にAML情報を開示するかどうかを決める
- b1が自身の情報を公開しているか
- b1がAを許可しているか
- b1がa1を許可しているか
- BがAを許可しているか
- もしb1が上記のいずれの条件も当てはまらない場合は、Bはb1に対して、Aに対して情報を開示しても良いかを問い合わせる必要がある
- この場合、BはAに対して、
info_status:"pending"のレスポンスを返す
- この場合、BはAに対して、
- もしBがb1の情報を開示する場合は、
dest_infoにb1のAML情報を格納してレスポンスを返す
- AがBのcomplianceチェックした結果を元に処理を行う
- Aは、もし
info_status:"pending"のレスポンスがBから返却されている場合、pending秒後に再度リクエストを行う - Aは、もし
dest_infoがBから返却されている場合、complianceチェックを行い、問題なければ、stellar networkに対してトランザクションを送信する
- Aは、もし
- Bが送金受理を行う
- Bがトランザクションハッシュのチェックまたはa1のcompliance再チェックを行う
- 問題なければ、Bはb1に対してクレジットを発行する
try out
- ここを見ながら、試してみます。
基本的には、以下のコラボレーションで動かす感じです。
- bridge server
- federation server
- compliance server
- stellar.toml hosting server
ここに構成を記載しています。
version: "2"
services:
stellar-kumano-te.com:
build: ./stellar
ports:
- "80:80"
- "443:443"
volumes:
- "./stellar/keys:/etc/nginx/keys"
- "./stellar/sites-enabled:/etc/nginx/sites-enabled"
- "./stellar/.well-known:/var/www/stellar-kumano-te.com/.well-known"
container_name: stellar-kumano-te.com
bridge-kumano-te.com:
build: ./bridge-server
ports:
- "8001:8001"
command: ./wait-for-it.sh bridge-db:3306 -t 600 -s -- ./bridge
depends_on:
- bridge-db
container_name: bridge-kumano-te.com
bridge-db:
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: bridge
MYSQL_DATABASE: bridge
MYSQL_USER: bridge
MYSQL_PASSWORD: bridge
TZ: JST
volumes:
- ./bridge-db/conf.d:/etc/mysql/conf.d
- bridge-db-data:/var/lib/mysql
container_name: bridge-db
federation-kumano-te.com:
build: ./federation-server
ports:
- "8002:8002"
command: ./wait-for-it.sh federation-db:3306 -t 600 -s -- ./federation
depends_on:
- federation-db
container_name: federation-kumano-te.com
federation-db:
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: federation
MYSQL_DATABASE: federation
MYSQL_USER: federation
MYSQL_PASSWORD: federation
TZ: JST
volumes:
- ./federation-db/init.d:/docker-entrypoint-initdb.d
- ./federation-db/conf.d:/etc/mysql/conf.d
- federation-db-data:/var/lib/mysql
container_name: federation-db
compliance-kumano-te.com:
build: ./compliance-server
ports:
- "8003:8003"
- "8004:8004"
command: ./wait-for-it.sh compliance-db:3306 -t 600 -s -- ./compliance
depends_on:
- compliance-db
container_name: compliance-kumano-te.com
compliance-db:
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: compliance
MYSQL_DATABASE: compliance
MYSQL_USER: compliance
MYSQL_PASSWORD: compliance
TZ: JST
volumes:
- ./compliance-db/conf.d:/etc/mysql/conf.d
- compliance-db-data:/var/lib/mysql
container_name: compliance-db
callbacks-kumano-te.com:
build: ./callbacks
ports:
- "8005:8005"
command: npm start
depends_on:
- bridge-db
- federation-db
- compliance-db
container_name: callbacks-kumano-te.com
volumes:
bridge-db-data:
driver: local
federation-db-data:
driver: local
compliance-db-data:
driver: local
tips
自己証明書を今回は使用したのですが、公式のbridge-serverは自己証明書だと動かないため
公式をフォークし修正したものを使用することにしました。
結果
以下を実行すると、各サーバーがコラボして、処理を行います。
(function() {
var request = require('request');
request.post({
url: 'http://localhost:8001/payment',
form: {
amount: '1',
asset_code: 'KumaDollar',
asset_issuer: 'GAOOFELY4CO2L4YWOVOEF2J233NF4XHVWTKFUUJU5QJO7UKJ2T2MBTR7',
destination: 'amy_smith*stellar-kumano-te.com',
source: 'SB5PJSVV3K62V3MSQGG6DKMNHR4BONGAEK5TTSMFPQCQZJE6RVHXWETN',
sender: 'tunde_adebayo*stellar-kumano-te.com',
// `extra_memo` is required for compliance (use it instead of `memo`)
extra_memo: 'Test transaction',
}
}, function(error, response, body) {
if (error || response.statusCode !== 200) {
console.error('ERROR!', error || body);
}
else {
console.log('SUCCESS!', body);
}
});
})();
> SUCCESS! {
"hash": "db4cee9cbec4ff13e11c23f20687f0742e6d2a999c62abc0682227d9e22efb21",
"result_xdr": "AAAAAAAAAGQAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAA=",
"ledger": 3903847
}
以下、docker-compose up上のログになります。
$ docker-compose up
Creating stellar-kumano-te.com ...
Creating compliance-db ...
Creating federation-db ...
Creating bridge-db ...
Creating stellar-kumano-te.com
Creating bridge-db
Creating compliance-db
Creating federation-db ... done
Creating compliance-kumano-te.com ...
Creating bridge-db ... done
Creating federation-kumano-te.com
Creating callbacks-kumano-te.com ...
Creating compliance-kumano-te.com
Creating bridge-kumano-te.com ...
Creating callbacks-kumano-te.com
Creating bridge-kumano-te.com ... done
Attaching to stellar-kumano-te.com, compliance-db, federation-db, bridge-db, federation-kumano-te.com, compliance-kumano-te.com, callbacks-kumano-te.com, bridge-kumano-te.com
compliance-db | 2017-09-12 03:40:27 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
compliance-db | 2017-09-12 03:40:27 0 [Note] mysqld (mysqld 5.6.36) starting as process 1 ...
federation-db | 2017-09-12 03:40:27 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
federation-db | 2017-09-12 03:40:27 0 [Note] mysqld (mysqld 5.6.36) starting as process 1 ...
bridge-db | 2017-09-12 03:40:28 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
bridge-db | 2017-09-12 03:40:28 0 [Note] mysqld (mysqld 5.6.36) starting as process 1 ...
federation-kumano-te.com | wait-for-it.sh: waiting 600 seconds for federation-db:3306
federation-kumano-te.com | wait-for-it.sh: federation-db:3306 is available after 0 seconds
federation-kumano-te.com | time="2017-09-12T03:40:29Z" level=info msg="starting federation server - devel" pid=1
federation-kumano-te.com | time="2017-09-12T03:40:29Z" level=info msg="listening on 0.0.0.0:8002" pid=1
compliance-kumano-te.com | wait-for-it.sh: waiting 600 seconds for compliance-db:3306
compliance-kumano-te.com | wait-for-it.sh: compliance-db:3306 is available after 0 seconds
compliance-kumano-te.com | time="2017-09-12T03:40:29Z" level=info msg="Starting external server on :8003"
compliance-kumano-te.com | time="2017-09-12T03:40:29Z" level=info msg="Starting internal server on :8004"
bridge-kumano-te.com | wait-for-it.sh: waiting 600 seconds for bridge-db:3306
bridge-kumano-te.com | wait-for-it.sh: bridge-db:3306 is available after 0 seconds
bridge-kumano-te.com | time="2017-09-12T03:40:30Z" level=info msg="Creating and initializing TransactionSubmitter"
bridge-kumano-te.com | time="2017-09-12T03:40:30Z" level=info msg="Initializing Authorizing account"
bridge-kumano-te.com | time="2017-09-12T03:40:30Z" level=info msg="Loading account" accountID=GAOOFELY4CO2L4YWOVOEF2J233NF4XHVWTKFUUJU5QJO7UKJ2T2MBTR7 service=Horizon
callbacks-kumano-te.com | npm info it worked if it ends with ok
callbacks-kumano-te.com | npm info using npm@5.3.0
callbacks-kumano-te.com | npm info using node@v8.4.0
callbacks-kumano-te.com | npm info lifecycle callbacks@1.0.0~prestart: callbacks@1.0.0
callbacks-kumano-te.com | npm info lifecycle callbacks@1.0.0~start: callbacks@1.0.0
callbacks-kumano-te.com |
callbacks-kumano-te.com | > callbacks@1.0.0 start /usr/local/src/callbacks
callbacks-kumano-te.com | > node index.js
callbacks-kumano-te.com |
callbacks-kumano-te.com | Bridge server callbacks running on port 8005!
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="Account loaded" accountID=GAOOFELY4CO2L4YWOVOEF2J233NF4XHVWTKFUUJU5QJO7UKJ2T2MBTR7 service=Horizon
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="Initializing Base account"
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="Loading account" accountID=GATLCZMS3ITTVSCM2VB55KT2I7OHHXOWD2QM6O4BNK5LQTD2A3T7DINC service=Horizon
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="Account loaded" accountID=GATLCZMS3ITTVSCM2VB55KT2I7OHHXOWD2QM6O4BNK5LQTD2A3T7DINC service=Horizon
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="TransactionSubmitter created"
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="Creating and starting PaymentListener"
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="Loading account" accountID=GATLCZMS3ITTVSCM2VB55KT2I7OHHXOWD2QM6O4BNK5LQTD2A3T7DINC service=Horizon
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="Account loaded" accountID=GATLCZMS3ITTVSCM2VB55KT2I7OHHXOWD2QM6O4BNK5LQTD2A3T7DINC service=Horizon
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="PaymentListener created"
bridge-kumano-te.com | time="2017-09-12T03:40:32Z" level=info msg="Started listening for new payments" accountId=GATLCZMS3ITTVSCM2VB55KT2I7OHHXOWD2QM6O4BNK5LQTD2A3T7DINC cursor=16765688307781633 service=PaymentListener
federation-kumano-te.com | time="2017-09-12T03:40:48Z" level=info msg="starting request" host="localhost:8002" ip="172.23.0.1:53858" method=GET path="/federation?q=amy_smith%2Astellar-kumano-te.com&type=name" pid=1 subsys=http
federation-kumano-te.com | time="2017-09-12T03:40:48Z" level=info msg="finished request" bytes=111 duration=2.857338ms pid=1 status=200 subsys=http
federation-kumano-te.com | time="2017-09-12T03:40:58Z" level=info msg="starting request" host="federation-kumano-te.com:8002" ip="172.23.0.7:41610" method=GET path="/federation?q=amy_smith%2Astellar-kumano-te.com&type=name" pid=1 subsys=http
federation-kumano-te.com | time="2017-09-12T03:40:58Z" level=info msg="finished request" bytes=111 duration=1.15153ms pid=1 status=200 subsys=http
compliance-kumano-te.com | time="2017-09-12T03:40:58Z" level=info msg=HandlerAuth data="{\"sender\":\"tunde_adebayo*stellar-kumano-te.com\",\"need_info\":false,\"tx\":\"AAAAACaxZZLaJzrITNVD3qp6R9xz3dYeoM87gWq6uEx6BufxAAAAZAAAAAAAAAAAAAAAAAAAAAO++vwHaNENts80IR5ZqBIHB8YMbPhEPQm5KvYKUsNC9gAAAAEAAAAAAAAAAQAAAAAmsWWS2ic6yEzVQ96qekfcc93WHqDPO4FqurhMegbn8QAAAAJLdW1hRG9sbGFyAAAAAAAAHOKReOCdpfMWdVxC6Tre2l5c9bTUWlE07BLv0UnU9MAAAAAAAJiWgAAAAAA=\",\"attachment\":\"{\\\"nonce\\\":\\\"1505187658244446627\\\",\\\"transaction\\\":{\\\"sender_info\\\":{\\\"address\\\":\\\"GATLCZMS3ITTVSCM2VB55KT2I7OHHXOWD2QM6O4BNK5LQTD2A3T7DINC\\\",\\\"first_name\\\":\\\"Tunde\\\",\\\"last_name\\\":\\\"Adebayo\\\"},\\\"route\\\":\\\"amy_smith\\\",\\\"note\\\":\\\"\\\",\\\"extra\\\":\\\"Test transaction\\\"},\\\"operations\\\":null}\"}" sig="czmn4BddjNlG6FWDN/oyan4gnCEi8BhsL6+b1L+JQL6szDzvaO/+JWUgGjp5yQg4a+Du9UvtYSc1srbSy++PAA=="
bridge-kumano-te.com | time="2017-09-12T03:41:05Z" level=info msg="Success response from horizon" ledger=0xc42033c228 service=Horizon
bridge-kumano-te.com | time="2017-09-12T03:41:05Z" level=info msg="New received payment" id=16766895193591809 service=PaymentListener
bridge-kumano-te.com | time="2017-09-12T03:41:06Z" level=info msg="Loaded memo" memo="vvr8B2jRDbbPNCEeWagSBwfGDGz4RD0JuSr2ClLDQvY=" service=PaymentListener type=hash
bridge-kumano-te.com | time="2017-09-12T03:41:06Z" level=info msg="Sending request to compliance server" body=map[memo:[vvr8B2jRDbbPNCEeWagSBwfGDGz4RD0JuSr2ClLDQvY=]] service=PaymentListener url="http://compliance-kumano-te.com:8004/receive"
callbacks-kumano-te.com | /receive
callbacks-kumano-te.com | { amount: '1.0000000',
callbacks-kumano-te.com | asset_code: 'KumaDollar',
callbacks-kumano-te.com | asset_issuer: 'GAOOFELY4CO2L4YWOVOEF2J233NF4XHVWTKFUUJU5QJO7UKJ2T2MBTR7',
callbacks-kumano-te.com | data: '{"sender":"tunde_adebayo*stellar-kumano-te.com","need_info":false,"tx":"AAAAACaxZZLaJzrITNVD3qp6R9xz3dYeoM87gWq6uEx6BufxAAAAZAAAAAAAAAAAAAAAAAAAAAO++vwHaNENts80IR5ZqBIHB8YMbPhEPQm5KvYKUsNC9gAAAAEAAAAAAAAAAQAAAAAmsWWS2ic6yEzVQ96qekfcc93WHqDPO4FqurhMegbn8QAAAAJLdW1hRG9sbGFyAAAAAAAAHOKReOCdpfMWdVxC6Tre2l5c9bTUWlE07BLv0UnU9MAAAAAAAJiWgAAAAAA=","attachment":"{\\"nonce\\":\\"1505187658244446627\\",\\"transaction\\":{\\"sender_info\\":{\\"address\\":\\"GATLCZMS3ITTVSCM2VB55KT2I7OHHXOWD2QM6O4BNK5LQTD2A3T7DINC\\",\\"first_name\\":\\"Tunde\\",\\"last_name\\":\\"Adebayo\\"},\\"route\\":\\"amy_smith\\",\\"note\\":\\"\\",\\"extra\\":\\"Test transaction\\"},\\"operations\\":null}"}',
callbacks-kumano-te.com | from: 'GATLCZMS3ITTVSCM2VB55KT2I7OHHXOWD2QM6O4BNK5LQTD2A3T7DINC',
callbacks-kumano-te.com | id: '16766895193591809',
callbacks-kumano-te.com | memo: 'vvr8B2jRDbbPNCEeWagSBwfGDGz4RD0JuSr2ClLDQvY=',
callbacks-kumano-te.com | memo_type: 'hash',
callbacks-kumano-te.com | route: 'amy_smith' }
bridge-kumano-te.com | time="2017-09-12T03:41
最後に
前回からの流れで、一通りstellarを使った金融サービスを構築する際の基本構成を試すことができました。
かなり得られた気づきがあり、とても良かったです。
個人的には、こういった構成やプロトコルはstellarに閉じた話ではないと感じましたので、応用していけたらと思います。
以上になります。