blockchain

Blockchain: Stellar Compliance Server

Tugasnya anchor salah satunya untuk menghandle regulatory compliance, seperti Anti-Money Laundering (AML). Untuk mencapai hal ini, kita harus menggunakan Stellar compliance protocol, sebuah cara standard untuk saling menukar informasi compliance dan transaksi yang belum di approve dengan institusi keuangan lainnya.

Kita bisa kembangkan compliance protocol sendiri, tapi Stellar.org sudah menyediakan compliance server yang bisa mengatur kerjaan compliance kita

Bridge server kita menghubungi compliance server dalam rangka meng-otorisasi sebuah transaction sebelum dikirim. Compliance server kita menggunakan compliance protocol untuk memastikan transaction sudah oke dengan compliance server disisi penerima, lalu menginformasukan ke bridge server bahwa transaction sudah ok untuk dikirim.

Ketika ada compliance server lain menghubungi kita untuk memastikan suatu transaction ok, kita gunakan serangkaian callbacks untuk mengecek informasi pada server kita. Kemudian, ketika bridge server kita menerima transaksi tersebut, dia menghubungi compliance server untuk mem-verify bahwa transaksi itu sudah ok.

Create Database

Compliance server memerlukan database MySQL or PostgreSQL untuk menyimpan transaksi dan compliance information. Buat dulu sebuah database baru yang namanya stellar_compliance dan user yang dapat mengaksesnya. Tidak perlu buat tabel apapun; karena server menyediakan perintah untuk menkonfigurasi dan mengupdate database kita. Cek disini.

Download dan Configure Compliance Server

Mulai dengan download versi terakhir compliance server untuk OS kita dan install pada suatu folder. Pada folder yang sama, buat file dengan nama config_compliance.toml. File ini berisi configuration untuk compliance server. Isinya seperti ini:

external_port = 8003
internal_port = 8004
# Set this to `true` if you need to check the information of a person receiving
# a payment you are sending (if false, only the sender will be checked). For
# more information, see the callbacks section below.
needs_auth = false
network_passphrase = "Test SDF Network ; September 2015"

[database]
type = "mysql" # Or "postgres" if you created a PostgreSQL database
url = "dbuser:dbpassword@/stellar_compliance"

[keys]
# This should be the secret seed for your base account (or another account that
# can authorize transactions from your base account).
signing_seed = "SAV75E2NK7Q5JZZLBBBNUPCIAKABN64HNHMDLD62SZWM6EBJ4R7CUNTZ"
encryption_key = "SAV75E2NK7Q5JZZLBBBNUPCIAKABN64HNHMDLD62SZWM6EBJ4R7CUNTZ"

[callbacks]
sanctions = "http://localhost:8005/compliance/sanctions"
ask_user = "http://localhost:8005/compliance/ask_user"
fetch_info = "http://localhost:8005/compliance/fetch_info"

# The compliance server must be available via HTTPS. Specify your SSL
# certificate and key here. If the server is behind a proxy or load  balancer
# that implements HTTPS, you can omit this section.
[tls]
certificate_file = "server.crt"
private_key_file = "server.key"

File configuration ini mendefinisikan external_port dan internal_port. External port harus bisa diakses dari public network. Ini adalah port yang akan dikontak oleh organisasi lain untuk menentukan apakah kita akan menerima transaksi pembayaran atau tidak.

Internal port tidak boleh bisa diakses dari public. Ini adalah port tempat dimana kita menginisiasi compliance operations dan men-transmit informasi private. Ini harus diprotek via firewall agar tidak bisa diakses dari luar.

Kita juga harus informasikan ke bridge server bahwa kita punya compliance server yang bisa digunakannya. Update file config_bridge.toml dengan mencantumkan address internal port dari compliance server kita:

port = 8001
horizon = "https://horizon-testnet.stellar.org"
network_passphrase = "Test SDF Network ; September 2015"
compliance = "https://your_org.com:8004"

# ...the rest of your configuration...

Implementasi Compliance Callbacks

Pada server configuration file, ada 3 callback URLs, mirip seperti yang ada pada bridge server. Callback ini adalah HTTP POST URL yang akan mengirimkan form-encoded data:

  • fetch_info dikasi sebuah federation address (seperti tunde_adebayo*your_org.com) dan harus mengeluarkan semua information yang diperlukan oleh organisasi lain untuk menjalankan compliance check. Isinya bisa berupa data apapun It can be any data yang kita rasa perlu dan harus berformat JSON.Ketika kita mengirim transaksi payment, callback ini akan dipanggil untuk mengambil informasi tentang customer yang mengirim payment tersebut agar mengirimkannya ke organisasi penerima payment. Ketika menerima payment, callback ini akan dipanggil jika sending organization meminta informasi tentang penerima untuk melakukan compliance checks (berdasarkan padaneeds_auth configuration).
    Contoh implementasi  fetch_info callback dengan JavaScript:
    app.post('/compliance/fetch_info', function (request, response) {
      var addressParts = response.body.address.split('*');
      var friendlyId = addressParts[0];
    
      // You need to create `accountDatabase.findByFriendlyId()`. It should look
      // up a customer by their Stellar account and return account information.
      accountDatabase.findByFriendlyId(friendlyId)
        .then(function(account) {
          // This can be any data you determine is useful and is not limited to
          // these three fields.
          response.json({
            name: account.fullName,
            address: account.address,
            date_of_birth: account.dateOfBirth
          });
          response.end();
        })
        .catch(function(error) {
          console.error('Fetch Info Error:', error);
          response.status(500).end(error.message);
        });
    });
    
  • sanctions dikasi informasi tentang orang yang mengirim payment kepada kita atau customer kita. Ini adalah data yang sama yang akan diterima server pengirim dari callback fetch_info-nya sendiri. HTTP response code yang dihasilkannya mengindikasikan apakah payment akan diterima (status 200), denied (status 403), atau kita perlu waktu untuk memprosesnya  (status 202).
    Contoh implementasi sanctions callback dengan JavaScript:
    app.post('/compliance/sanctions', function (request, response) {
      var sender = JSON.parse(request.body.sender);
    
      // You need to create a function to check whether there are any sanctions
      // against someone.
      sanctionsDatabase.isAllowed(sender)
        .then(function() {
          response.status(200).end();
        })
        .catch(function(error) {
          // In this example, we're assuming `isAllowed` returns an error with a
          // `type` property that indicates the kind of error. Your systems may
          // work differently; just return the same HTTP status codes.
          if (error.type === 'DENIED') {
            response.status(403).end();
          }
          else if (error.type === 'UNKNOWN') {
            // If you need to wait and perform manual checks, you'll have to
            // create a way to do that as well
            notifyHumanForManualSanctionsCheck(sender);
            // The value for `pending` is a time to check back again in seconds
            response.status(202).json({pending: 3600}).end();
          }
          else {
            response.status(500).end(error.message);
          }
        });
    });
    
  • ask_user dipanggil ketika menerima payment jika pengirim meminta informasi tentang penerima. Callback ini mengeluarkan code mengindikasikan apakah kita akan mengirimkan informasi tersebut (fetch_info yang akan dipanggil kemudian untuk mengambil informasinya). Ia dikirimi informasi pada sisi payment dan sender.
    Contoh implementing ask_user callback pada JavaScript:
    app.post('/compliance/ask_user', function (request, response) {
      var sender = JSON.parse(request.body.sender);
    
      // You can do any checks that make sense here. For example, you may not
      // want to share information with someone who has sanctions as above:
      sanctionsDatabase.isAllowed(sender)
        .then(function() {
          response.status(200).end();
        })
        .catch(function(error) {
          if (error.type === 'UNKNOWN') {
            // If you need to wait and perform manual checks, you'll have to
            // create a way to do that as well.
            notifyHumanForManualInformationSharing(sender);
            // The value for `pending` is a time to check back again in seconds
            response.status(202).json({pending: 3600}).end();
          }
          else {
            response.status(403).end();
          }
        });
    });
    

Untuk menyederhanakan, kita tambahkan ketiga callbacks ini pada server yang sama dengan callback-nya bridge server. Namun, kita bisa saja memasangnya pada server lain. Pastikan saja bahwa URL-nya bisa diakses dari yang membutuhkan.

Update Stellar.toml

Ketika organisasi lain perlu men-contact compliance server kita untuk mengotorisasi payment kepada customer kita, mereka pertama kali akan mengcek file domain stellar.toml untuk menemukan address-nya, sama seperti ketika mencari federation server.

Untuk compliance operations, kita perlu tambahkan 2 properti pada stellar.toml:

FEDERATION_SERVER = "https://www.your_org.com:8002/federation"
AUTH_SERVER = "https://www.your_org.com:8003"
SIGNING_KEY = "GAIGZHHWK3REZQPLQX5DNUN4A32CSEONTU6CMDBO7GDWLPSXZDSYA4BU"

AUTH_SERVER adalah address bagi external port compliance server kita. Seperti federation server, ini bisa URL apapun yang kita mau, tapi harus support HTTPS dan menggunakan SSL certificate yang valid.

SIGNING_KEY adalah public key yang cocok cengan secret seed yang ditentukan untuk signing_seed pada konfigurasi compliance server. Organisasi lain akan menggunakannya untuk mem-verify bahwa pesan memang berasal dari kita.

Menjalankan Server

Sebelum menjalankan server untuk pertama kali, perlu dibuat dulu tables pada database. Dengan menjalankan compliance server dengan argumen --migrate-db akan membuat tabel yang diperlukan:

./compliance --migrate-db

Setiap kali kita update compliance server ke versi yang lebih baru, kita perlu jalankan command ini lagi. Ia akan meng-upgrade database kita jikalau ada sesuatu yang perlu diubah.

Setelah database ready, kita bisa jalankan compliance server dengan cara:

./compliance

Coba!

Kita coba mengirim payment ke seseorang yang menjalankan compliance dan federation servers.

Cara termudah adalah mencoba payment dari  salah satu customers ke yang lain another. Compliance, federation, dan bridge servers kita akan menjalankan kedua sisi transaksi sending dan receiving.

Kirim payment melalui bridge server, tapi kali ini gunakan federated addresses untuk sender dan receiver dan sebuah extra_memo untuk men-trigger compliance checks:

Contoh send Payment dengan JavaScript:
var request = require('request');

request.post({
  url: 'http://localhost:8001/payment',
  form: {
    amount: '1',
    asset_code: 'USD',
    asset_issuer: 'GAIUIQNMSXTTR4TGZETSQCGBTIF32G2L5P4AML4LFTMTHKM44UHIN6XQ',
    destination: 'amy*your_org.com',
    source: 'SAV75E2NK7Q5JZZLBBBNUPCIAKABN64HNHMDLD62SZWM6EBJ4R7CUNTZ',
    sender: 'tunde_adebayo*your_org.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);
  }
});

Untuk test yang lebih realistic, jalankan masing-masing 2 bridge, federation, dan compliance servers pada domain yang berbeda dan kirim payment!

Contoh source code script di atas bisa ambil dari sini ya..

https://github.com/akhdaniel/stellar

 

Akhmad D. Sembiring
Blockchain Expert Indonesia