rvasp

package module
v0.0.0-...-97e514b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 24, 2020 License: MIT Imports: 16 Imported by: 0

README

rVASP

Robot VASP for TRISA demonstration and integration

This is a simple gRPC server that implements a UI workflow and messaging framework to demonstrate sending and receiving transactions using the TRISA InterVASP protocol. The server was built to support a demonstration UI that requires a streaming interface so that a live message flow is achieved. However, the communication protocol between rVASPs also demonstrates how implementers might go about writing InterVASP services in their own codebases. The architecture is as follows:

Architecture

Generating Protocol Buffers

To regenerate the Go and Python code from the protocol buffers:

$ go generate ./...

This will generate the Go code in pb/ and the Python code in pb/rvaspy. Alternatively you can manually generate the code to specify different directories using the following commands:

$ protoc -I . --go_out=plugins=grpc:. api.proto
$ python -m grpc_tools.protoc -I . --python_out=./rvaspy --grpc_python_out=./rvaspy api.proto

Quick Start

To get started using the rVASP, you can run the local server as follows:

$ go run ./cmd/rvasp serve

The server should now be listening for TRISADemo RPC messages. To send messages using the python API, make sure you can import the modules from rvaspy - the simplest way to do this is to install the package in editable mode as follows:

$ pip install -e ./rvaspy/

This will use the setup.py file in the rvaspy directory to install the package to your $PYTHON_PATH. Because it is in editable mode, any time you regenerate the protocol buffers or pull the repository, the module should be updated on the next time you import. An example script for using the package is as follows:

import rvaspy

api = rvaspy.connect("localhost:4434")

cmds = [
    api.account_request("robert@bobvasp.co.uk"),
    api.transfer_request("robert@bobvasp.co.uk", "mary@alicevasp.us", 42.99)
]

for msg in api.stub.LiveUpdates(iter(cmds)):
    print(msg)

Note that the RVASP api client is not fully implemented yet.

Containers

We are currently not using a container repository, so to build the docker images locally, please run the following steps in order:

  1. Build the root Docker image tagged as trisacrypto/rvasp:latest
  2. Build the alice, bob, and evil containers in containers/, tagging them appropriately
  3. Use docker-compose to run the three rVASPs locally

To simplify the build process, we have added a script that builds all 4 images. You can execute the building script as follows:

$ ./containers/rebuild.sh

Then all that's needed is to run docker-compose up to get the robot VASPs running locally.

Documentation

Index

Constants

View Source
const (
	NaturalPersonAlias  = 0
	NaturalPersonBirth  = 1
	NaturalPersonMaiden = 2
	NaturalPersonLegal  = 3
	NaturalPersonMisc   = 4
)

Natural person name type codes

View Source
const (
	LegalPersonLegal   = 0
	LegalPersonShort   = 1
	LegalPersonTrading = 2
)

Legal person name type codes

View Source
const (
	AddressTypeHome       = 0
	AddressTypeBusiness   = 1
	AddressTypeGeographic = 2
)

Address type codes

View Source
const (
	NationalIdentifierARNU = 0 // Alien registration number
	NationalIdentifierCCPT = 1 // Passport number
	NationalIdentifierRAID = 2 // Registration authorrity identifier
	NationalIdentifierDRLC = 3 // Driver license number
	NationalIdentifierFIIN = 4 // Foreign investment identity number
	NationalIdentifierTXID = 5 // Tax identification number
	NationalIdentifierSOCS = 6 // Social security number
	NationalIdentifierIDCD = 7 // Identity card number
	NationalIdentifierLEIX = 8 // Legal entity identifier (LEI)
	NationalIdentifierMISC = 9 // Unspecified
)

National identifier type codes

View Source
const (
	VersionMajor = 1
	VersionMinor = 0
	VersionPatch = 0
)

Version component constants for the current build.

Variables

This section is empty.

Functions

func LookupAccount

func LookupAccount(db *gorm.DB, account string) *gorm.DB

LookupAccount by email address or wallet address.

func LookupBeneficiary

func LookupBeneficiary(db *gorm.DB, beneficiary string) *gorm.DB

LookupBeneficiary by email address or wallet address.

func MigrateDB

func MigrateDB(db *gorm.DB) (err error)

MigrateDB the schema based on the models defined above.

func Version

func Version() string

Version returns the semantic version for the current build.

Types

type Account

type Account struct {
	gorm.Model
	Name          string          `gorm:"not null"`
	Email         string          `gorm:"uniqueIndex;not null"`
	WalletAddress string          `gorm:"uniqueIndex;not null;column:wallet_address"`
	Wallet        Wallet          `gorm:"foreignKey:WalletAddress;references:Address"`
	Balance       decimal.Decimal `gorm:"type:numeric(15,2);default:0.0"`
	Completed     uint64          `gorm:"not null;default:0"`
	Pending       uint64          `gorm:"not null;default:0"`
	IVMS101       string          `gorm:"column:ivms101;not null"`
}

Account contains details about the transactions that are served by the local VASP. It also contains the IVMS 101 data for KYC verification, in this table it is just stored as a JSON string rather than breaking it down to the field level. Only customers of the VASP have accounts.

func (Account) BalanceFloat

func (a Account) BalanceFloat() float32

BalanceFloat converts the balance decmial into an exact two precision float32 for use with the protocol buffers.

func (Account) TableName

func (Account) TableName() string

TableName explicitly defines the name of the table for the model

func (Account) Transactions

func (a Account) Transactions(db *gorm.DB) (records []Transaction, err error)

Transactions returns an ordered list of transactions associated with the account ordered by the timestamp of the transaction, listing any pending transactions at the top. This function may also support pagination and limiting functions, which is why we're using it rather than having a direct relationship on the model.

type IVMS101Address

type IVMS101Address struct {
	AddressType        int      `json:"address_type"`
	Department         string   `json:"department,omitempty"`
	SubDepartment      string   `json:"sub_department,omitempty"`
	StreetName         string   `json:"street_name"`
	BuildingNumber     string   `json:"building_number,omitempty"`
	BuildingName       string   `json:"building_name,omitempty"`
	Floor              string   `json:"floor,omitempty"`
	PostBox            string   `json:"post_box,omitempty"`
	Room               string   `json:"room,omitempty"`
	PostCode           string   `json:"post_code,omitempty"`
	TownName           string   `json:"town_name,omitempty"`
	TownLocationName   string   `json:"town_location_name,omitempty"`
	DistrictName       string   `json:"district_name,omitempty"`
	CountrySubDivision string   `json:"country_sub_division,omitempty"`
	AddressLine        []string `json:"address_line"`
	Country            string   `json:"country"`
}

IVMS101Address is used to specify a geographic address in a country.

type IVMS101LegalNameIdentifier

type IVMS101LegalNameIdentifier struct {
	LegalPersonName     string `json:"legal_person_name"`
	LegalPersonNameType int    `json:"legal_person_name_identifier_type"`
}

IVMS101LegalNameIdentifier is used to collect single legal names with type codes.

type IVMS101NameIdentifier

type IVMS101NameIdentifier struct {
	PrimaryIdentifier   string `json:"primary_identifier"`
	SecondaryIdentifier string `json:"secondary_identifier"`
	NameIdentifierType  int    `json:"name_identifier_type"`
}

IVMS101NameIdentifier is used to collect name information with type codes.

type IVMS101NationalIdentification

type IVMS101NationalIdentification struct {
	NationalIdentifier     string `json:"national_identifier"`
	NationalIdentifierType int    `json:"national_identifier_type"`
	CountryOfIssue         string `json:"country_of_issue"`
	RegistrationAuthority  string `json:"registration_authority"`
}

IVMS101NationalIdentification is an identifier issued by an appropriate issuing authority

type IVMS101Person

type IVMS101Person struct {
	NaturalPerson struct {
		Name struct {
			NameIdentifiers         []*IVMS101NameIdentifier `json:"name_identifiers"`
			LocalNameIdentifiers    []*IVMS101NameIdentifier `json:"local_name_identifiers"`
			PhoneticNameIdentifiers []*IVMS101NameIdentifier `json:"phonetic_name_identifiers"`
		} `json:"name,omitempty"`
		Address                []*IVMS101Address              `json:"geographic_addresses"`
		NationalIdentification *IVMS101NationalIdentification `json:"national_identification"`
		CustomerIdentification string                         `json:"customer_identification"`
		DateAndPlaceOfBirth    struct {
			DateOfBirth  string `json:"date_of_birth"`
			PlaceOfBirth string `json:"place_of_birth"`
		} `json:"date_and_place_of_birth"`
		CountryOfResidence string `json:"country_of_residence"`
	} `json:"natural_person"`
	LegalPerson struct {
		Name struct {
			NameIdentifiers         []*IVMS101LegalNameIdentifier `json:"name_identifiers"`
			LocalNameIdentifiers    []*IVMS101LegalNameIdentifier `json:"local_name_identifiers"`
			PhoneticNameIdentifiers []*IVMS101LegalNameIdentifier `json:"phonetic_name_identifiers"`
		} `json:"name"`
		Address                []*IVMS101Address              `json:"geographic_addresses"`
		CustomerNumber         string                         `json:"customer_number"`
		NationalIdentification *IVMS101NationalIdentification `json:"national_identification"`
		CountryOfRegistration  string                         `json:"country_of_registration"`
	} `json:"legal_person,omitempty"`
}

IVMS101Person is a top level representation of IVMS101 data that can be serialized or deserialized into JSON for database storage. This data can also be extracted from a protocol buffer representation sent between VASPs.

type Identity

type Identity struct {
	gorm.Model
	WalletAddress string `gorm:"not null;column:wallet_address"`
	Wallet        Wallet `gorm:"foreignKey:WalletAddress;references:Address"`
	IVMS101       string `gorm:"column:ivms101;not null"`
	Provider      string `gorm:"not null"`
	Hash          string `gorm:"not null"`
}

Identity holds IVMS 101 data for an originator or a beneficiary that was sent as part of the transaction process. This should not be stored in the wallet since the wallet is a representation of the local VASPs knowledge about customers and bercause the identity information could change between transactions. This intermediate table is designed to more closely mimic data storage as part of a blockchain transaction. The hash is used to assist with deduplicating identities

func (Identity) TableName

func (Identity) TableName() string

TableName explicitly defines the name of the table for the model

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server implements the GRPC TRISAInterVASP and TRISADemo services.

func New

func New(dsn string) (s *Server, err error)

New creates a rVASP server with the specified configuration and prepares it to listen for and serve GRPC requests.

func (*Server) AccountStatus

func (s *Server) AccountStatus(ctx context.Context, req *pb.AccountRequest) (rep *pb.AccountReply, err error)

AccountStatus is a demo RPC to allow demo clients to fetch their recent transactions.

func (*Server) LiveUpdates

func (s *Server) LiveUpdates(stream pb.TRISADemo_LiveUpdatesServer) (err error)

LiveUpdates is a demo bidirectional RPC that allows demo clients to explicitly show the message interchange between VASPs during the InterVASP protocol. The demo client connects to both sides of a transaction and can push commands to the stream; any messages received by the VASP as they perform the protocol are sent down to the UI.

func (*Server) Serve

func (s *Server) Serve(addr string) (err error)

Serve GRPC requests on the specified address.

func (*Server) Shutdown

func (s *Server) Shutdown() (err error)

Shutdown the TRISA Directory Service gracefully

func (*Server) Transfer

func (s *Server) Transfer(ctx context.Context, req *pb.TransferRequest) (rep *pb.TransferReply, err error)

Transfer accepts a transfer request from a beneficiary and begins the InterVASP protocol to perform identity verification prior to establishing the transactoin in the blockchain between crypto wallet addresses.

type Transaction

type Transaction struct {
	gorm.Model
	AccountID     uint            `gorm:"not null"`
	Account       Account         `gorm:"foreignKey:AccountID"`
	OriginatorID  uint            `gorm:"column:originator_id;not null"`
	Originator    Identity        `gorm:"foreignKey:OriginatorID"`
	BeneficiaryID uint            `gorm:"column:beneficiary_id;not null"`
	Beneficiary   Identity        `gorm:"foreignKey:BeneficiaryID"`
	Amount        decimal.Decimal `gorm:"type:numeric(15,2)"`
	Debit         bool            `gorm:"not null"`
	Completed     bool            `gorm:"not null;default:false"`
	Timestamp     time.Time       `gorm:"not null"`
}

Transaction holds exchange information to send money from one account to another.

func (Transaction) AmountFloat

func (t Transaction) AmountFloat() float32

AmountFloat converts the amount decmial into an exact two precision float32 for use with the protocol buffers.

func (Transaction) TableName

func (Transaction) TableName() string

TableName explicitly defines the name of the table for the model

type VASP

type VASP struct {
	gorm.Model
	Name     string     `gorm:"uniqueIndex;size:255;not null"`
	URL      *string    `gorm:"null"`
	Country  *string    `gorm:"null"`
	Endpoint *string    `gorm:"null"`
	PubKey   *string    `gorm:"null"`
	NotAfter *time.Time `gorm:"null"`
	IsLocal  bool       `gorm:"column:is_local;default:false"`
	IVMS101  string     `gorm:"column:ivms101"`
}

VASP is a record of known partner VASPs and caches TRISA protocol information. This table also contains IVMS101 data that identifies the VASP (but only for the local VASP - we assume that VASPs do not have IVMS101 data on each other and have to use the directory service for that). TODO: modify VASP ID to a GUID

func (VASP) TableName

func (VASP) TableName() string

TableName explicitly defines the name of the table for the model

type Wallet

type Wallet struct {
	gorm.Model
	Address    string `gorm:"uniqueIndex"`
	Email      string `gorm:"uniqueIndex"`
	ProviderID uint   `gorm:"not null"`
	Provider   VASP   `gorm:"foreignKey:ProviderID"`
}

Wallet is a mapping of wallet IDs to VASPs to determine where to send transactions. Provider lookups can happen by wallet address or by email.

func (Wallet) TableName

func (Wallet) TableName() string

TableName explicitly defines the name of the table for the model

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL