Step 4 - FATF Travel Rule Solution

Ok, so now that we have a verified TA account and a user account, we can demonstrate how Shyft can be integrated so that VASPs can comply with the FATF Travel Rule.

Lets simulate how VASP US can discover the beneficiary of a BTC transaction.

Suppose John on VASP US wants to withdraw his BTC. Typically he will log on to VASP US and upload a withdrawal BTC address and instruct VASP US to withdraw BTC to the BTC address. Let’s assume this BTC address is a deposit address on another VASP which is associated with another user (not John). This is the address: 1J8NSTQMG9VGeEakd8pCyWz2QVNsqmDkbs

With the SDK you can set an Attestation, we call it a WALLET Attestation. Just before VASP US executes the withdraw of BTC to address 1J8NSTQMG9VGeEakd8pCyWz2QVNsqmDkbs, VASP US can execute a WALLET Attestation to the network.

Here is the function call to set this Attestation:

// node -e 'require("./vs-sdk").trustAnchorSetAttestation(user_account, 1, "", "", "WALLET", "1J8NSTQMG9VGeEakd8pCyWz2QVNsqmDkbs", "BTC", is_managed, ta_account)'
module.exports.trustAnchorSetAttestation = function (user_account, jurisdiction, effective_time, expiry_time, public_data, documents_matrix_encrypted, availability_address_encrypted, is_managed, ta_account) {
trustAnchorSetAttestation(user_account, jurisdiction, effective_time, expiry_time, public_data, documents_matrix_encrypted, availability_address_encrypted, is_managed, ta_account);
};

The above function call of trustAnchorSetAttestation executes the following code:

function trustAnchorSetAttestation(user_account, jurisdiction, effective_time, expiry_time, public_data, documents_matrix_encrypted, availability_address_encrypted, is_managed, ta_account) {
public_data = convertToByte32(public_data);
console.log('public_data');
console.log(public_data);
documents_matrix_encrypted = packDocumentsMatrixEncrypted(documents_matrix_encrypted);
documents_matrix_encrypted = convertToByte32(documents_matrix_encrypted);
console.log('documents_matrix_encrypted');
console.log(documents_matrix_encrypted);
availability_address_encrypted = convertToByte32(availability_address_encrypted);
console.log('availability_address_encrypted');
console.log(availability_address_encrypted);
(async () => {
tas = await TrustAnchorStorage.deployed();
result = await tas.setAttestation.call(user_account, jurisdiction, effective_time, expiry_time, public_data, documents_matrix_encrypted, availability_address_encrypted, is_managed, {from: ta_account});
console.log('setAttestation result');
console.log(result);
hash = await tas.setAttestation(user_account, jurisdiction, effective_time, expiry_time, public_data, documents_matrix_encrypted, availability_address_encrypted, is_managed, {from: ta_account});
console.log('setAttestation hash');
console.log(hash);
})();
}

Note: for the public_data, documents_matrix_encrypted and availability_address_encrypted we assign WALLET, BTC, 1J8NSTQMG9VGeEakd8pCyWz2QVNsqmDkbs respectively.

One great feature of Shyft is that VASPs on the network can listen for specific events, in this case the EVT_setAttestation event.

Here is the setup for listening for these events.

function setupTrustStorageManagerListeners() {
(async () => {
tas = await TrustAnchorStorage.deployed();
tas.EVT_setAttestation().on('data', (event) => {
console.log('EVT_setAttestation');
console.log(event);
trustAnchorGetAttestationComponents(event['returnValues']['attestationKeccak']);
}).on('error', function(error){
console.log(error);
});
console.log("setupTrustStorageManagerListeners EVT_setAttestation success");
})();
}

When VASPs subscribe to Attestation events, they will receive data from the network like this:

{
"returnValues": {
"attestationKeccak": "0x3e08f70a6624c42ffe915cf49ee309dadf48e2f40e85e3500d7ae0d956185f12",
"msg_sender": "0xF3339c2CAE33dCb4Fd7a9640AFcFA5944D62976C",
"_identifiedAddress": "0xA3A10fe8406EF65C9d337c8c36113A5FD2248C2d",
"_jurisdiction": "1",
"_effectiveTime": "1552853002",
"_expiryTime": "1616097802",
"_publicData_0": "0x57414c4c4554",
"_documentsMatrixEncrypted_0": "0x6c554d516763545550564b386d745077456341434f77532b4c3143676a7a477457776377714267463855355979413370317543693356565a344a6a376b2f342f715a473345356663346175356a427066636b5039635872536377766e442b777031384a7a426c6c4f50503547534668342f37672b544b2f4871514c3432627371526a7171316764664671764d636f30574b4a6265542f3752536e7464704557763651436d4531446832525a646f6c565633754656572f5466383652742f51373476715077494e56474c65576939336d586e7752776c71773d",
"_availabilityAddressEncrypted": "0x4254430000000000000000000000000000000000000000000000000000000000",
"_isManaged": true
},
"event": "EVT_setAttestation",
"signature": "0xa079ed41279e715fc167d089286c3d5533d37ab590064b033dcb3aa68f7bab30"
}
}

In the event you can see the TA address 0xF3339c2CAE33dCb4Fd7a9640AFcFA5944D62976C and the user address 0xA3A10fe8406EF65C9d337c8c36113A5FD2248C2d along with the components.

Any TA receiving this event can unpack the components to view the data.

Let’s assume one of the VASPs on the network discovers in the components of the Attestation that it is a WALLET type Attestation for a BTC address: 1J8NSTQMG9VGeEakd8pCyWz2QVNsqmDkbs.

Let’s also assume that this address is known to the other VASP EUR. Through the discovery layer on the network, this VASP can look up which VASP set this Attestation by TA address lookup.

The VASP that ‘owns’ this BTC address can look up the TA address in the event data and learn that the TA is VASP US. Through an off-chain communication, both VASPs can directly share sender and beneficiary of this BTC transaction.

Here is the logic flow between these two VASPs.

VASP USVASP EUR
Set Wallet Attestation with BTC address
Catch Attestation Event, BTC address is known to VASP EUR
Look up TA in discovery layer using TA address in the Attestation
Send Beneficiary Information Off-Chain, with Attestation User Address
Receive message from VASP EUR, look up user by Shyft User Address
Send Sender Information Off-Chain to VASP EUR
VASP US has both Sender and Beneficiary KYC infoVASP EUR has both Sender and Beneficiary KYC info