Giter VIP home page Giter VIP logo

facilitator's People

Contributors

0xsarvesh avatar abhayks1 avatar benjaminbollen avatar bruce9steve avatar gulshanvasnani avatar jayeshbairagi avatar kreloaded avatar puneet-khushwani-eth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

facilitator's Issues

Worker: Update database with hashlock and unlockSecret.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This function gets the hashLock and unlockSecret pair as the parameter, this call a function on DB interaction layer object to store this in the database.

Define the interfaces for all the functions in Facilitator

Worker facilitates the stake and mint process.

  • It reads the stake requested data from the database.
  • It gets the worker address for the database for each chain.
  • It unlocks the worker address account.
  • It updates the database with the current status of facilitation.
    For more details check the epic #1

This ticket is about defining the interfaces of all the functions in the Worker.

The proposed functions are provided for reference.
The implementer can think this in detail and can add/remove functions.

  • Constructor
    - Accepts mosaic-config, facilitator-config as parameter.
    • Accepts Config object. (store in variable).
    • Creates DB object. (store in variable). (Still in discussion)
  • function to start the worker.
- [ ] **function to get pending items from `stake_request` table. (Create the ticket for this.) - [ ] **function that handles the state machine** (Create a new ticket for this.) - [ ] **function to get the message status from messageOutbox of the gateway.** - [ ] **function to get the message status from messageInbox of the cogateway.** - [ ] **function to get the latest `stateRoot` from the anchor contract (auxiliary chain).**
  • function to update DB with the latest state of facilitation. (Task execution table) (Update the ticket).
    - REQUESTED

    • ACCEPTED
    • ACCOUNT_PROVEN
    • STAKE_INTENT_COMFIRMED
    • PROGRESS_STAKE
    • PROGRESS_MINT
    • COMPLETE
  • function to update DB with hashlock and unlockSecret.
    - [ ] function to update DB with proof data.

- [ ] **function to unlock worker address.** - Get the encrypted_account from Config for the given address. - Read the password from the env variable. - Decrypt the account. - Add it to web3 account wallet. The accounts will be unlocked at the commander level and will update the web3 wallet.
  • function to create hashLock and unlockSecret.

    • Generate hashlock and unlockSecret pair
  • function to approve bounty amount.

  • function to accept stake request.

  • function to generate account proof.

  • function to confirm stake intent.

  • function to progress stake.

  • function to progress mint.

- [ ] **function to stop the worker (handle SIGTERM).** (update the ticket.)

Worker: Generate hashLock and unlockSecret.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This function will generate random unlockSecret and hashlock pair.

Facilitator: Start the scanner child-process.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #3 first for any updates in interface and params.

The facilitator will start the scanner process to listen to the StakeRequested event.

  • Start a new child-process for Scanner.ts (store in a variable).
  • Implement the callbacks.

Facilitator: Validate gateways.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #3 first for the interface.

Once StakeRequested event is received by the scanner they pass the event data to the facilitator,
The facilitator needs to check if the gateway contract address from the event is supported by the facilitator.

  • This function will accept the gateway contract address
  • Get the gateway contract address from the config to validate it.
  • Check if the given contract address is in config contract address.
  • Return boolean result (Implementor can decide)

Scanner: Get events from the given transaction.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #4 first for any updates in params.

This function will receive transaction receipts.

  • Parse the events
  • Check for the StakeRequested event
  • Return the event if found.

Commander: Facilitator list

The proposed command is as given below, the implementer can improvise this.

  • List command.
./facilitator list 
  • The facilitator's which are started can be listed by ./facilitator list command.

  • Help command.
./facilitator --help

  • This command provides help for the facilitator command.

Worker: Accept stake request.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This function used contract interact to call accept stake request on OSTComposer contract.

  • Updates the state in DB. (There is a function that will handle this by passing the state)
    -ACCEPTED if the transaction is successful
    -ACCEPTED_FAILED if the transaction is failed.
  • Should wait for n block confirmations.

Listener: Define the interfaces for all the functions in Listener

The scanner listener reads each and every block from the chain and looks for StakeRequested event for the given composer contract. Once the event is found it callbacks the facilitator with event data.
scanner listener keeps a record of the last block scanned so that it can resume the scanner listener from the same block height. For more details check the epic #1

The scanner listener can be for the origin and auxiliary chain.
The scanner listener should update the database tables.

This ticket is about defining the interfaces of all the functions in the scanner listener.

The proposed functions are provided for reference.
The implementer can think this in detail and can add/remove functions

We can call this as EventListner.

  • constructor.
    - Accepts mosaic-config and facilitator-config.

    • Accepts Config object. (store in variable).
    • Accepts object that cointains {contractAddresss: [Event topics]}.
    • Creates DB object. (store in variable). (Still in discussion)
  • function to scan the blocks in batches. (Start scan)

    • Accepts blockNumber as a parameter.
    • blockNumber is an optional param, if this is provided then the scanner listener will start scanning from that block, else it will start from the latest block.
    • Keep track of last block number that was scanned.

- [ ] function to update the last scanned block number.
- [ ] function to get transactions for the given block.
- [ ] function to get events from the given transaction.
- [ ] function to emit an event when StakeRequested event is found.

  • function to stop the scanner listener (SIGTERM). (Update the ticket)

- [ ] function to updates stake_request table status. (create a new ticket for this.)

Commander: Define schema for process management

Story

As a facilitator developer,
I want to ensure that it is possible to run only a single instance of each process like a facilitator, scanner per chain
So that I can avoid any possible race conditions. (Using same worker key)

Each process can make entry to Database when they start. Each process should be uniquely identified.

Scenarios:

When there is no existing process running,
If I start a type of process like (Scanner or facilitator) for a chain
It should successfully run the process.

When there is an existing process running of a type,
If I start the process for a chain with the same worker keys,
It should break the process with an appropriate message.

Worker: Get the message status from message outbox of the gateway.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This function is to get the message status from the outbox of messageBox in origin chain (source).
This will be used by the worker to check the latest status of the facilitation from the chain before it performs the actual stake and mint facilitation.

Commander: Implement facilitator commands

These are the commands that can be used to run the facilitators.

The proposed command is as given below, the implementer can improve this.

  • Facilitator command.
./facilitator  --mosaic-config <mosaic_config_file_path> --facilitator-config <facilitator_config_file_path> --chain-id <chain-id>

  • The facilitator can be started by ./facilitator.
  • mosaic_config_file_path is the path for the mosaic.json file.
  • facilitator_config_file_path is the path for the facilitator.json file.
  • chain-id must be the value of the chainid to be started.
  • If the config path is not provided then the default path is used.
    • $HOMEDIR/.mosaic/ethereum.json
    • $HOMEDIR/.mosaic/ropsten.json
    • $HOMEDIR/.mosaic/<chain-id>/facilitator.json
  • Facilitation must be done for one auxiliary chain.
  • Password will be taken in interactive mode
  • DB [Chain Id => unique key]

  • Help command.
./facilitator --help

  • This command provides help for the facilitator command.

Facilitator: Start the worker child-process.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #3 first for any updates in interface and params.

  • This will get an identifier as a param. This identifier is the primary id in DB.
  • Start a new child-process for Worker.ts (store in a variable)
  • Implement the callbacks
  • Get worker addresses for both chains
  • If worker addresses are available then update the entity in the DB with the process id and worker addresses, send the params to child-process to start facilitation, else log error.

Config: Validate facilitator-config contents

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #2 first for any updates in params.

The facilitator-config file provided must be verified before we start the facilitator.

Implement the function to validate the facilitator-config.

  • Check #2 for the interface of the function.
  • Define the facilitator-config schema.
  • Validate if facilitator-config against the schema. contains all the mandatory params required for facilitation.
    • RPC endpoint for the chains
    • worker addresses.
  • Validate DB configs, if it exists or not.
  • use npm tool to match against schema

Define the interfaces for all the functions in Config

Config provides all the data that is needed to run the facilitator. It reads data from mosaic-config and facilitator-config JSON files and provides getter functions that can be used in other parts of the facilitator code base.

This ticket is about defining the interfaces of all the functions in the Config.

The proposed functions are provided for reference.
The implementer can think this in detail and can add/remove functions.

  • constructor
    • Accepts mosaic-config and facilitator-config as params
    • Validates config (against schema for facilitator-config : mosaic-config)
    • Validate worker addresses


  • function to get DB path.
    [Check DB tickets if more functions related to DB are needed]

  • function to get RPC endpoints for the given chain.

  • function to get all the worker addresses for the given chain.

  • function to get encrypted_account for a given address.

  • function to get OSTComposer contract address

  • function to get all Gateway contract addresses.

  • function to get Gateway contract address for a given chain.

  • function to get CoGateway contract address for a given chain.

  • function to get worker addresses for a given chain.


Example of mosaic-config.json is given below.

{
  "originChain": {
    "chainId": 3,
    "contractAddresses": { // Contracts deployed on origin chain, should be reused for all auxiliary chains. 
      "simpleTokenAddress": "",
      "merklePatriciaLibAddress": "",
      "GatewayLibAddress": "",
      "messageBusAddress": ""
    }
  },
  "auxiliaryChains": {
    "1406": {
      "chainId": 1406,
      "bootNodes": [], //List of boot nodes
      "genesis": {}, 
      "contractAddresses": { // Contract addresses specific to single auxiliary chain 
        "origin": { // Contracts deployed on origin chain specific to single auxiliary chain
          "anchorOrganizationAddress": "",
          "anchorAddress": "",
          "ostGatewayOrganizationAddress": "",
          "ostEIP20GatewayAddress": "",
          "ostComposerAddress": "" 
        },
        "auxiliary": { // Contracts deployed on the auxiliary chain
          "ostPrimeAddress": "",
          "anchorOrganizationAddress": "",
          "anchorAddress": "",
          "merklePatriciaLibAddress": "",
          "GatewayLibAddress": "",
          "messageBusAddress": "",
          "ostCoGatewayOrganizationAddress": "",
          "ostEIP20CogatewayAddress": ""
        }
      }
    },
    "1407": {
      "chainId": 1407,
      "bootNodes": [], //List of boot nodes
      "genesis": {},
      "contractAddresses": { // Contract addresses specific to single auxiliary chain 
        "origin": { // Contracts deployed on origin chain specific to single auxiliary chain
          "anchorOrganizationAddress": "",
          "anchorAddress": "",
          "ostGatewayOrganizationAddress": "",
          "ostEIP20GatewayAddress": "",
          "ostComposerAddress": ""
        },
        "auxiliary": { // Contracts deployed on the auxiliary chain
          "ostPrimeAddress": "",
          "anchorOrganizationAddress": "",
          "anchorAddress": "",
          "merklePatriciaLibAddress": "",
          "GatewayLibAddress": "",
          "messageBusAddress": "",
          "ostCoGatewayOrganizationAddress": "",
          "ostEIP20CogatewayAddress": ""
        }
      }
    }
  }
}

Example of facilitator-config.json is given below.

{
    "db": {
            "db_path": "<db_path>",
            // other params
    },
    "chains": {
        <chain_id_1>: {
                   "rpc": "http://localhost:3000",
                   "workers": [0xaddress1, 0xaddress2],
		},
	<chain_id_2>: {
                  "rpc": "http://localhost:4000",
                  "workers": [0xaddress3, 0xaddress4]
		}	
	}
    "encrypted_accounts": {
        "0xaddress1": {
        
        },
        "0xaddress2": {
        
        },
        "0xaddress3": {
        
        },
        ,
        "0xaddress4": {
        
        }
    }
}

Config: Parse facilitator-config json file to populate the config variables.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #2 first for the interface.

Config provides an easy way to read the config from mosaic-config and facilitation-config

  • #2 will define the properties that are exposed from the config.
  • This issue is about parsing the facilitator config JSON file and populate the class variables.

Scanner: Get transactions for the given block.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #4 first for any updates in params.

This function will get the block header.

  • Get the transactions hash for the block
  • Get each transaction receipt for the given transaction hash.
  • Filter the receipts for the OSTComposer contracts.
  • Return the transactions receipts.

Worker: Progress stake.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This function does the following.

  • Call contract interacts of Gateway to perform the progressStake transaction.
  • Update the state in DB. (There is a function that will handle this by passing the state)
    - PROGRESS_STAKE if the transaction is successful
    - PROGRESS_STAKE_FAILED if the transaction is failed.
  • Should wait for n block confirmations.

Facilitator: Handle SIGTERM

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #3 first for any updates in interface and params.

If the process encounters SIGTERM, then it should be intercepted.

  • Should inform the child-process about the SIGTERM.
  • Wait for child-process to complete
  • Exit the process.

Config: constructor

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #2 first for any updates in params.

Implement the constructor function for Config.

  • Accepts mosaic-config and facilitator-config as params.
  • Validates mosaic-config.
  • Validates facilitator-config.
  • Validates worker addresses.

Commander : Facilitator Stop command

These are the commands that can be used to run the facilitators.

The proposed command is as given below, the implementer can improvise this.

  • Stop command.
./facilitator stop  --chainid <chainId> 

  • The facilitator can be stopped by ./facilitator stop.
  • chainid is the chainid value to be stopped.

  • Help command.
./facilitator --help

  • This command provides help for the facilitator command.

DB: Implement StakeRequest model

The ticket is about implementation of StakeRequest model.

  • Create folder models.

  • Create class StakeRequest inside models directory which will interact with stake_requests table.

  • All model classes which interacts with database tables should be put in models directory.

  • Create script to create stake_requests table. SequelJS has good support for migrations. https://sequelize.readthedocs.io/en/latest/docs/migrations/

StakeRequest model stores stake requests information and their processing status. Below is the proposed schema of stake_requests table.

Note: This will give a rough idea, the schema can be improved by the implementer.

name | type | references | description
-- | -- | -- | --
"id" | INTEGER |   | Primary Key
"stake_request_hash" | VARCHAR |   | Unique Key.
"message_hash" | VARCHAR |   |  
"origin_chain_id" | INTEGER |   |  
"aux_chain_id" | INTEGER |   |  
"gateway_address" | VARCHAR |   |  
"origin_worker_address" | VARCHAR |   |  
"auxiliary_worker_address" | VARCHAR |   |  
"hash_lock" | VARCHAR |   |  
"unlock_secret" | VARCHAR |   |  
"status" | INTEGER |   | 
"created_at" | DATETIME |  | Time when the record was created
"updated_at" | DATETIME | | Time when worker completed it's process 

Proposed STATUS Values (Add/Remove if needed)

REQUESTED
ACCEPTED
ACCEPTED_FAILED
ACCOUNT_PROVEN
ACCOUNT_PROVEN_FAILED
STAKE_INTENT_CONFIRMED
STAKE_INTENT_CONFIRMED_FAILED
PROGRESS_STAKE
PROGRESS_STAKE_FAILED
PROGRESS_MINT_COMPLETE
PROGRESS_MINT_FAILED
UNKNOWN

StakeRequest model should define methods for below use cases:

  • Define status enum values.

  • Method to fetch stake requests waiting for processing and mark them as in progress. After fetching the pending stake requests, update worker address(auxiliary or origin), updated_at in the table. We can process the requests in batches also.

  • Method to insert new entry for StakeRequested event in stake_requests table.

  • Method to update the status, updated_at in stake_requests table for a given stake_request_hash.

Facilitator init command.

This command will create the facilitator config file.
The proposed command is

./facilitator init 
    --mosaic-config <mosaic_config_path> 
    --chain-id <aux_chainId> 
    --origin-password  <origin_password>
    --aux-password  <aux_password>
    --origin-rpc <RPC_endpoint> 
    --aux-rpc <RPC_endpoint> 
    --db-path <db_path>
    --db-username <db_user_name>
    --db-password <db_password>

--db-path, --db-username, --db-password are optional, if it is passed then given values will be used, otherwise new db, username and password is created, and added to config.

  • Given the chain-id (auxiliary chain id), the origin chain id can be retrieved using mosaic-config.
  • This will generate the ethereum address for both the chains using the password provided.
  • Encrypts the keystore file.
  • Creates the facilitator config file.
  • The location of the file is written at ./mosaic/<chain>/facilitator-config.json.
  • If the file exists already then the file generation should fail.
{
    "db": {
            "db_path": "<db_path>",
            // other params
    },
    "chains": {
        <chain_id_1>: {
                   "rpc": "http://localhost:3000",
                   "workers": [0xaddress1, 0xaddress2],
		},
	<chain_id_2>: {
                  "rpc": "http://localhost:4000",
                  "workers": [0xaddress3, 0xaddress4]
		}	
	}
    "encrypted_accounts": {
        "0xaddress1": {
        
        },
        "0xaddress2": {
        
        },
        "0xaddress3": {
        
        },
        ,
        "0xaddress4": {
        
        }
    }
}

Facilitator: constructor

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #3 first for any updates in params.

Implement the constructor function for Facilitator.

  • Accepts mosaic-config, facilitator-config and chain[] as params.
  • Creates Config object. (store in the variable)
  • Creates a DB object. (store in the variable)
  • Call function to start event scanner child-process. (store in the variable)
  • Call function to resume facilitation.

Chain[] param is optional if it is provided then the facilitation will be supported to these chains only.
By default, the facilitation is supported for all the chains specified in facilitator-config.

Worker: Progress mint.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This function does the following.

  • Call contract interacts of CoGateway to perform the progressMint transaction.
  • Update the state in DB. (There is a function that will handle this by passing the state)
    - PROGRESS_MINT if the transaction is successful
    - PROGRESS_MINT_FAILED if the transaction is failed.
  • Should wait for n block confirmations.

Facilitator: Handle SIGTERM.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

If the process encounters SIGTERM, then it should be intercepted.

  • This should wait for any ongoing transactions to complete.
  • unsubscribe from listening to the graph-node entities.
  • close all the open connections (Implementer can think if there are any such open connections. e.g: DB).
  • Exit the process.

Worker: Update database with the latest state of facilitation.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

The idea here is that this function will call update state function on DB object.

Check this ticket for the states
#42

Config: Validate worker address from the facilitator-config.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #2 first for interface and any updates in params.

Worker address provided in the config must be validated so that they can be used for facilitation.

  • Get the worker address for each chain
  • Validate if encrypted_account for the address is available.
  • Validate if the password is available in the env variable. The env variable name will be in the following format MOSAIC_ADDRESS_PASSW_<address>
  • Validate if we can unlock the account and have access to the private key.

Facilitator: Keep track of balance of worker address.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

Implement a function that checks the balance of worker address before performing the task.

The implementer can think of logic to optimize this, instead of querying the balance every time, the balance can be stored into a variable at the time of initialization. After each transactions, the balance can be updated.

Worker: Confirm stake intent.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This function does the following.

  • Generate the proof data (function exists)
  • Call contract interacts of CoGateway to perform the confirmStakeIntent transaction.
  • Update the state in DB. (There is a function that will handle this by passing the state)
    • STAKE_INTENT_CONFIRMED if the transaction is successful
    • STAKE_INTENT_CONFIRMED_FAILED if the transaction is failed.
  • Should wait for n block confirmations.

DB Setup

The ticket is about setting up DB and defining npm to interact with the databases tables.

  • Setup docker+mysql sqlite. If we decide to chose any other database, update the docker accordingly.

  • Use a good javascript npm/library for interacting with database. Below npm can be used. It also supports migration.
    http://docs.sequelizejs.com/

Acceptance criteria of the ticket is to run a sqlite mysql node and connect it with nodejs npm.

Implement Facilitator Class

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in params.

It should be able to perform the following:

  • Subscribe to the events in the model object.
  • Model objects will poll the database table, if a new item in the table, it will decompose the transactions, and call the callbacks(emit events).
  • The callbacks can execute the tasks (as per the state machine).
    example of tasks:
    • Accept stake request
    • Confirm stake intent
    • Progress stake
    • Progress mint.
  • The facilitator keeps the track of its own transaction of tasks.

Scanner: Update the last scanned block number.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #4 first for any updates in params.

This function is to update the database with the latest block number that was scanned.
This will be useful when the scanner starts, it can resume the scanning from that block number.

The implementer can decide the table schema.

Worker: Approve bounty amount.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This is a function that uses the contract interacts to approve the bounty amount.

Config: Validate the mosaic-config content

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #2 first for any updates in params.

The mosiac-config file provided must be verified before we start the facilitator.

Implement the function to validate the mosaic-config.

  • Check #2 for the interface of the function.
  • Validate if mosaic-config contains all the (mandatory and facilitator) params required for facilitation against mosaic schema, see schema mosaic-chains #44
    • Composer address
    • Gateway address
    • Identify more.
  • use npm tool to match against schema
  • Assert the address from the chain.
  • Save the config in the variable (Implementor can decide the details)

Worker: Get the message status from message inbox of the cogateway.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This function is to get the message status from the inbox of messageBox in auxiliary chain (target).
This will be used by the worker to check the latest status of the facilitation from the chain before it performs the actual stake and mint facilitation.

Worker: Get account proof.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

This function does the following.

  • Gets the latest outbox message state (function exists to do this)
  • Generates the proof data.

Scanner: Callback when `StakeRequested` event is found.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #4 first for any updates in params.

Once the event is received.
Inform the parent process about the event data.
This function will accept the event data and send the message to the parent process id.

Facilitator: Determine if gasPrice / gasLimit is sufficient to perform facilitations.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #3 first for any updates in interface and params.

  • Check if the gasLimit is high enough to perform the stake and mint facilitation.
  • Check if the gasPrice provided is at par to perform stake and mint facilitation.

For now, the par values will be in constants.

Scanner: Handle SIGTERM.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #4 first for any updates in interface and params.

If the process encounters SIGTERM, then it should be intercepted.

  • Should inform the parent process about the SIGTERM.
  • Exit the process.

Facilitator: Unlock worker address.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #5 first for any updates in interface and params.

The worker addresses will perform the actual transaction, so they must be unlocked before.
This function will perform the following.

  • Get the encrypted_account from Config for the given address.
  • Read the password from the env variable.
  • Decrypt the account.
  • Add it to web3 account wallet.

The password should be available in the environment variable. The key will be in the format MOSAIC_ADDRESS_PASSW_<address>. This is a proposal, the implementer can improvise.

Define the interfaces for all the functions in Facilitator.

Facilitator.ts is the main file that is responsible for the facilitation

  • This creates new child-process like block scanner, worker, etc
  • This reads the callback from all the child-process and performs required actions.
  • For details check the epic #1

This ticket is about defining the interfaces of all the functions in the Facilitator.

The proposed functions are provided for reference.
The implementer can think this in detail and can add/remove functions.

  • constructor

    • Accepts mosaic-config and facilitator-config as params.
    • Creates Config object. (store in variable)
    • Creates DB object. (store in variable)
    • Call function to start event scanner child-process. (store in variable)
    • Call function to resume facilitation.
  • function to validate gateways.

    • Once an event is received, check if the gateway contract address is suported by the facilitator.
    • Get the gateway contract address from the config to validate it.
  • function to start the event scanner child-process.

    • Start a new child-process for Scanner.ts (store in a variable)
    • Implement the call backs
  • function to resume facilitation.

    • Get any pending or failed facilitation from DB.
    • loop through the items and call function to start the worker child-process (Store in a variable).
  • function to start the worker child-process.

    • This will get an identifier as a param. This identifier is the primary id in DB.
    • Start a new child-process for Worker.ts (store in a variable)
    • Implement the callbacks
    • Get worker addresses for both chains
    • If worker addresses are available then update the entity in the DB with the process id and worker addresses, send the params to child-process to start facilitation, else log error.
  • function to select worker address for chains.

    • Get the last worker address used for the chain from the DB.
    • Get all the workers from the Config.
    • Select the next worker in round-robin
    • Validate if the worker addresses have Eth/Base token to perform transactions.
    • If validated then return the worker address else select other worker address.
    • If no worker available throw exception. (or return undefined)
  • function to determine if gasPrice / gasLimit is sufficient to perform facilitations.

  • function to handle SIGTERM

Scanner: constructor

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #4 first for any updates in params.

Implement the constructor function for Scanner.

  • Accepts mosaic-config and facilitator-config.
  • Creates Config object. (store in the variable).
  • Creates DB object. (store in the variable).

Facilitator: Resume facilitation.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #3 first for any updates in interface and params.

  • Get any pending or failed facilitation from DB.
  • loop through the items and call function to start the worker child-process (Store in a variable).

Commander: Command line tool for starting listener processes

Below is the proposed commander for starting listeners. Before this ticket, schema for process management should be finalized.

Create a migration script to create the finalized process management schema.

./listener start --mosaic-config <mosaic-config-path> --facilitator-config <facilitator-config-path> --chain-id <chain-id>

Facilitator

Facilitator (Executable):

  • The executable must be able to support multiple chains simultaneously.

  • Support multiple workers (acceptStakeRequest & progressStake) simultaneously. (Q: private keys are held on node, or on client side? A: on the client side, local machine)

  • Subscribe / Scan StakeRequested event.

  • Workers should avoid race on acceptStakeRequest; eg round-robin

  • Track the gas available for each worker, if the worker gas too low to perform any transaction then it must not do facilitation.

  • Calculate if the gasPrice and gasLimit should be acceptable to do facilitation. (What's the threshold value? for now, we can use a constant value)

  • It must act as a hunter for any failed facilitation. (Out of scope for now.)

  • Handle SIGTERM gracefully.

  • Should be able to resume facilitation if it was not complete.

  • It should track the states of each step of facilitation in DB. Update the DB with the latest state e.g REQUESTED, ACCEPTED, PROGRESSED, etc.

  • Manage hash lock and unlock secret.


config.json :


{
    "db_path": "<db_path>",
    "chains": {
        <chain_id_1>: {
            "rpc": "http://localhost:3000",
            "ws": "ws://localhost:3001",
            "workers": [0xaddress1, 0xaddress2],
            "composer_address": "0xcomposerContractAddress",
            "supported_gateway_address": ["0xgatewayContractAddress_1", "0xgatewayContractAddress_2"]
		},
		<chain_id_2>: {
            "rpc": "http://localhost:4000",
            "ws": "ws://localhost:4001",
            "workers": [0xaddress3, 0xaddress4]
		}	
	}
    "encrypted_accounts": {
        "0xaddress1": {
        
        },
        "0xaddress2": {
        
        },
        "0xaddress3": {
        
        },
        ,
        "0xaddress4": {
        
        }
    }
}
  • db_path: Database file path
  • chains: Contains details of all the chains.
  • chain_id: Actual chain id number.
  • rpc: RPC end point.
  • ws: Websocket end point.
  • workers: Account address that can perform facilitation for the given chain
  • composer_address: Composer contract address for the given chain
  • supported_gateway_address: Supported gateway contract address. If StakeRequested event will have the gateway address other than specified here, that will be not taken for facilitation.
  • encrypted_accounts: This are the encrypted account that is generated by web3.eth.accounts.wallet.add(account); Here is a reference https://web3js.readthedocs.io/en/1.0/web3-eth-accounts.html#wallet-add

Please note:

  • If RPC and WS endpoints are not provided in the config file, then try to use localhost + default port
  • If composer_address and supported_gateway_address both are provided for the origin chain only. This will be checked to start the event scanner.

Proposal:

Commands :

1. Start facilitator :

./facilitator start <config_file_path> --chains <specific chain ids>
  • config_file_path: This is the path for the config file. If this is not provided then the facilitator will look at the default location.
  • --chains: This option is used to specify the chain ids that facilitator should facilitate. This will be origin chain ids

2. help :

./facilitator --help
  • Provides the help on how to use the command.

Executable :


When facilitator starts.

  1. Update the config file.
  2. Execute command ./facilitator start
  3. The facilitator will validate the config files and the chain ids if it is supported.
  4. The facilitator will start the event scanner.
  5. The facilitator will check the DB for the pending facilitation.
  6. The facilitator will fork worker processes for the pending tasks. (Updates the DB entry with PID). PID is the process id of the worker process. This PID indicates that the facilitator is in progress.
  7. The worker will query the latest state of the transactions from the chain and performs the facilitation accordingly.

When facilitator gets the StakeRequested events.

  1. The facilitator will validate the Event data.

  2. The facilitator will check if the gateway is supported.

  3. The facilitator will check the addresses table to get the origin and auxiliary chain pair and addresses related to that.

  4. If the address table does not have any data for the given chain id and gateway pair, then query the contract and get all the addresses and update the table.

  5. Facilitator gets the worker addresses for the origin and auxiliary chain.

  6. Facilitator forks a new worker child process and gets the PID.

  7. Facilitator inserts a new entry in thestake_requests table. This includes the stateRequestHash, chain id, gateway address, stake params, worker address of both chains, pid, state .. etc.

  8. The worker creates the hash lock and unlock secret. Unlocks the accounts. Performs accept stake request. Updates the stake_requests table with the latest state.

  9. Worker checks if the latest state root is committed in the auxiliary chain. If it is committed then it proceeds with the facilitator. If it is not committed then it will give a call back to Facilitator and stop the process.

    The facilitator can try to resume facilitation in time intervals, or there can be a new child process that can observe the state root commit event from the anchor, and give a call back to the facilitator. The facilitator can resume the facilitation.

On Handle SIGTERM:

  1. All the process should handle the SIGTERM
  2. If the child process gets the SIGTERM, complete the existing task and inform the parent process (facilitator).
  3. If parent process (facilitator) get he sigterm then inform the child process to terminate and wait till the child process are stopped.

Example

const { fork } = require('child_process');


const scanner = fork('scan_events.ts', args); 
// TODO: Check how we can pass chain Id as and argument in the above statement.

// If we cannot pass the chain Id then we can use send command to
scanner.send({ chain_is: 3 });
// Listen call back.
scanner.on('message', (event) => {
  	console.log('Event received', event);
	// Update DB
	// Do things here
	facilitate(event);
});


function facilitate(event) {
	// Check if gateway address is known
	// Check if gasPrice and gasLimit is sufficient to perform facilitation.
	// Get worker address (round robin .. etc.)
	// Validate worker address can perform transactions.
	// Fork a new child process to do facilitation.

	const facilitator = fork('facilitate.js'); 
	facilitator.send(< Object with all params that are needed for facilitation>);

	// Subscribe to all the events to handle the callbacks
    }
    

Facilitator as a hunter:

There can be one more child process that can act as Hunter which keeps looking for stake and mint events. Not in the scope for now.

DB proposal:

Please note: This will give a rough idea, the schema can be improved by the implementer.

This executable should resume any pending or failed task when started. To enable this the status of each StakeRequest must be persisted. We can use a database to achieve this (e.g: sqlite3).

All the child process have the access to read, insert and update contents in the DB.

stake_requests

name type references description
"stake_request_hash" VARCHAR   The unique identifier for the table type.
"message_hash" VARCHAR  
"origin_chain_id" INTEGER  
"gateway_address" VARCHAR  
"origin_account_address" VARCHAR  
"auxiliary_account_address" VARCHAR  
"hash_lock" VARCHAR  
"unlock_secret" VARCHAR  
"transactions" VARCHAR   This will contain transaction hashed of the events(json string)
"pid" INTEGER   This is process id, this is assigned when the facilitation is in progress by a worker process.
"state" INTEGER   Enum :

REQUESTED
ACCEPTED
ACCOUNT_PROVEN
STAKE_INTENT_COMFIRMED
PROGRESS_STAKE
PROGRESS_MINT
COMPLETE


addresses

name type references description
"orign_chain_id" INTEGER  
"gateway_address" VARCHAR  
"auxiliary_chain_id" VARCHAR  
"composer_address" VARCHAR  
"cogateway_address" VARCHAR  
"anchor_address" VARCHAR  
"co_anchor_address" VARCHAR  

facilitator.ts

  • This is the main file.
  • This forks a new child-process (scanner, worker, etc).
  • Listen to the events from all the child process and perform actions.
  • Handles SIGTERM.
  • At startup it checks the DB for pending, incomplete and failed facilitation tasks and forks new worker process accordingly.

scanner.ts

  • This file scans the blocks, gets the transactions, gets the event of the transactions in batches.
  • Keeps track of last scanned block number in memory.
  • It always scans from the latest block when started.
  • Emits event when StakeRequested event is found.

worker.ts

  • This file basically does the facilitation.
  • This will have an ethereum address associated with it in the variable (this is provided by the facilitator.ts while forking the new child-process)
  • The password for this address should be in the ENV variable password_0xethereumAccountAddress, that can be used for unlocking.
  • This always checks the latest state from the chain while progressing the task.
  • This will generate the hashLock and unlockSecret. Update DB with these values to keep track in case this process dies.
  • On every step of stake and mint, update the Status in DB.
  • Emit event when stake and mint are successful or failed.

Tickets:

  1. Create a new repository. (Done)

  2. Finalize config.json (Review and suggest)

  3. Finalize DB schema. (Review and suggest)

  4. Finalize the enum value for states column instake_request table.

  5. Implement DB interaction layer

    • create tables if does not exists.
    • function to insert new entry for StakeRequested event in stake_requests table.
    • function to update the state in stake_requests.
    • function to insert proof data in stake_requests.
    • function to insert and update worker address in stake_requests.
    • function to insert and update PID value in stake_requests.
    • function to insert new entry for addresses table.
  6. Implement block scanner.

    • Scan from the latest block when the process starts.
    • Keep track of last block number that was scanned.
    • function to validate the chain configs
    • function to scan the blocks in batches
    • function to get transactions
    • function to get event from the transactions
    • function to emit an event when StakeRequested event is found.
    • Handle SIGTERM to inform parent process.
  7. Add commander: ./facilitator start and ./facilitator --help

    following the proposed command

    ./facilitator start <config_file_path> --chains <specific_chain_ids>
    
    • The facilitator can be started by ./facilitator start.
    • config_file_path is the path for the config file. If this is not provided then the default path is used.
    • --chains <specific_chain_ids> this options can be used to specify the chains. The config file may have many chains specified, if this option is provided then the facilitator will start the process for this specific chains only. By default, it will start the process for all origin chains.
  8. Implement worker. (can mosaic.js facilitator be used?)

    • This process will do facilitation.
    • Updates the DB with the latest state of facilitation.
    • function to unlock worker address.
    • function to create hash lock and unlock secret.
    • function to approve bounty amount.
    • function to accept stake request.
    • function to generate a proof.
    • function to confirm stake intent.
    • function to progress stake.
    • function to progress mint.
    • Handle SIGTERM to inform parent process.
  9. Implement Facilitator

    • validates the config files.
    • function to validate gateways.
    • function to start the event scanner.
    • function to resume facilitation.
    • function to start the worker process.
    • listen to call backs of all the child processes.
    • function to select proper worker address for chains.
    • function to determine if gasPrice and gasLimit is sufficient to perform facilitations.
    • Handle SIGTERM to inform parent process.
  10. Update readme

Scanner: Scan the blocks in batches.

This is an implementation ticket. The actual implementation may vary as we start working on it.
Please check #4 first for any updates in params.

  • Accepts blockNumber as a parameter.
  • blockNumber is an optional param, if this is provided then the scanner will start scanning from that block, else it will start from the latest block
  • Keep track of last block number that was scanned.
  • Updates the database with the latest block number that was scanned.

Listener: Subscribe/Listen to the events, update the database

In the constructor, we get the chain id. From this chain id we know if its origin chain or auxiliary chain.
We can get the contract address from the config that the listener is interested in listening to the events.
The event/topic names, model identifier is hardcoded for the contract type in the code.
ABI's are available in mosaic-contract NPM package for decoding the events.

The implementer can decide how we update the database.

  • Listen to the events with some block delay.
  • insert/update the tables in the database using models.

All the events related to OSTComposer, Anchor, Gateway, and CoGateway.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.