Carpooling for Byteballers - The Great Byteball Bot War, week 3

in #byteball6 years ago

In the progress report last week I gave some possible options what features to add next. I decided to focus on the core functionality since the final deadline is coming up very soon, the fancy stuff can be added after the main idea is implemented. Three major functionality had been added this week:

  • smart contract, created when passenger checks in for the ride
  • ride completion algorithm and Carpool Oracle
  • payout processor

All three are quite heavy on core byteball features so let's see each one of them in detail. And as always, don't forget to check out the test site that runs on the Byteball testnet

Smart contract to pay for the ride

At check-in time, a smart contract is generated by the bot on behalf of the driver and the passenger. The contract is conditionally bound to the completion of the ride. If the ride is completed, eg. reached it's agreed destination, the funds are released to the driver, if not, the passenger is refunded. Note that a separate smart contract is created for each passenger should more people shared the ride, but structurally all contracts look the same.
The contract has four conditions:

  1. allows the bot to transfer the funds from the contract to the driver if the ride is completed
  2. allows the bot to transfer the funds from the contract to the passenger if the ride is not completed
  3. allows the driver to transfer the funds to any address if the ride is completed
  4. allows the passenger to transfer the funds to any address if the ride is not completed

To make this project functional, the last two conditions would be sufficient since that would allow the driver to get paid or the passenger to get refunded. However, in those cases the user have to make an effort to transfer the money out of the contract. Imagine a situation with 4 passengers. That would mean there are 4 contracts between the driver and the passengers so the driver would have 4 sub-wallets. That is a little too fragmented way to store the money, most people would like to aggregate these payments into let's say a "Byteball Carpool Earnings" wallet. To make it easier for the users, the bot takes care of moving the funds from the contracts to the driver's or passengers' payout address. Please note, that the contract does not allow the bot to transfer the money to any address, it is strictly enforced that it can only pay out either the driver or the passenger depending on the ride status.

An example of such payout can be seen in unit bNifUzUD6yOuuPkJ9konMIYum/NANAgbvMZZHvB8Uf0=. The smart contract address was YLCTO727JCV2K66LN2KCFJBYI7QIHF4Q and you can see its definition by clicking on the Definition link to unfold it. Let's take a closer look at it.

The root of the contract is an OR condition which has 4 arguments, the 4 conditions mentioned above. Let's examine the first condition that allows the bot to pay out the driver:

      [
         "and",
         [
            [
               "address",
               "PQVQTRUU6YLMWAX63ASSLLQSQIP5QE76"
            ],
            [
               "has",
               {
                  "what": "output",
                  "asset": "base",
                  "amount_at_least": 500,
                  "address": "N6SOYZHMRFTGDOY52GOYJ6UQ5E3WZBZD"
               }
            ],
            [
               "in data feed",
               [
                  [
                     "PQVQTRUU6YLMWAX63ASSLLQSQIP5QE76"
                  ],
                  "RIDE_STATUS",
                  "=",
                  "RIDE-3-COMPLETED"
               ]
            ]
         ]
      ]

Here you can see there are 3 sub-conditions that have to be true in order for the bot to pay the driver:

  • address: it is used to authenticate who can spend the contract. The address provided belongs to the carpool bot and it is only the bot that can prove the ownership of that address by adding it's signature to the transaction.
  • has: this condition is an introspection. It says that the transaction must transfer at least 500 bytes to N6SOYZHMRFTGDOY52GOYJ6UQ5E3WZBZD which is the driver's payout address he or she entered in the Carpool website profile page.
  • in data feed: it creates a condition on a value published by a 3rd party oracle. Well, in this case the 3rd party is the carpool bot itself, but it's a 3rd party for the passenger and the driver. This condition is only true if the carpool oracle (PQVQTRUU6YLMWAX63ASSLLQSQIP5QE76) posts a RIDE-3-COMPLETED value in its RIDE_STATUS data feed.

The second condition is very much the same, except it allows the bot to transfer the funds to the passenger if the RIDE_STATUS is INCOMPLETE. Next, let's look into the 3rd condition, which allows the driver to spend the funds (imagine a situation when the bot fails to pay out due to a bug or a network error):

      [
         "and",
         [
            [
               "address",
               "N6SOYZHMRFTGDOY52GOYJ6UQ5E3WZBZD"
            ],
            [
               "in data feed",
               [
                  [
                     "PQVQTRUU6YLMWAX63ASSLLQSQIP5QE76"
                  ],
                  "RIDE_STATUS",
                  "=",
                  "RIDE-3-COMPLETED"
               ]
            ]
         ]
      ]

We can see a similar pattern repeating: use the address to authenticate the driver (N6SOYZHMRFTGDOY52GOYJ6UQ5E3WZBZD is the address the driver provided to the carpool bot), then use the in data feed to verify if the ride status is COMPLETED. Only if these two conditions evaluate to true can the driver withdraw the funds.

The fourth condition is quite the same as the third one with the exception that it allows the passenger to refund him- or herself.

For implementation details, see the smart contract source code in RideFeeContract.js

Carpool Oracle

The role of the Carpool Oracle is to provide factual information about the ride status. It observes the real world and makes the information available in the Byteball DAG so smart contract conditions can be built on them. It can either state that a ride is completed or not. It acts as an independent 3rd party that has no self-interest to lean to either outcome.

The Carpool Oracle publishes its factual observations in the form of a data feed. The structure is quite simple, it's basically a key-value pair where the key is the name of the data feed, in this case RIDE_STATUS, and the value is the observed outcome of the ride, for example RIDE-1-COMPLETED or RIDE-1-INCOMPLETE. The number in between is the unique identifier of the individual ride. An example can be seen here: pqLuZmAhcAnW9uMRZWgTYGtBMBxgNl7CYOfMpPQzShI=

You may ask, how on Earth this oracle would know if a ride is completed or not? It's a valid question and the quality of the service depends highly on the how well we can answer this question. Ok, here it is. Each ride has a couple of participants, at least 1 driver and 1 passenger, but in a carpooling situation there are probably 3-4 people sharing the same ride. At the moment they reach the destination, the driver marks the ride completed which at he same time reads the GPS coordinates of his or her device and sends it to the carpool bot. The bot calculates a distance from the planned destination proportional to the total ride and comes up with a score between 0 and 100. We are not finished yet. The bot waits until at least 67% of the participants mark the ride completed. So now it's the passengers' turn to signal completion. Their GPS coordinates are read and the completion score is calculated based on their distance from the destination. The individual completion scores are then averaged and the final score is calculated. If the average score is more than 95, the ride is deemed completed. As a result the ride status is determined based on the geographical distance from the destination of random people.

Of course, the passengers could form a cartel and wait with completing the ride until they are far from the destination and "down vote" the driver. To somewhat handle that scenario, passengers that don't report their location within a given time frame could be punished with giving them a completion score of 100%. It's not implemented yet.

The oracle runs as a background job, periodically checking if there are completed rides. You can find the source code here in CarpoolOracle.js.

Payout processor

The payout processor is listening on DAG events and when a Carpool Oracle data feed entry becomes stable (confirmed) it triggers the payout flow. The payout cannot happen earlier than the confirmation of the ride status data feed transactions because the contract unlocks only on stable Byteball transactions.

The bot saves the transaction identifiers (aka unit) of each data feed post the Carpool Oracle creates. Then it listens on the my_transactions_became_stable events which supplies a list of units that just became stable. If there is a unit that matches the Carpool Oracle ones, it looks up the corresponding ride and reservations, collects the contract address and payout addresses of the driver and passengers and based on the ride status it makes a payout to either the driver or the passengers.

Source code can be found in PayoutProcessor.js.

What's next

The core functionality has been implemented already, but there are countless improvements to make. Some are:

  • create a smart contract definition template to reduce the transaction fee paid when moving the funds from the smart contract
  • provide feedback to the driver when the passengers have made a payment to the smart contract
  • charge X percent fee on each smart contract for providing the carpool bot services
  • all the ideas from last week: chat based interface for booking a ride, adding name using real name attestation
Sort:  

Congratulations @byteball.market! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You received more than 250 upvotes. Your next target is to reach 500 upvotes.

Click here to view your Board
If you no longer want to receive notifications, reply to this comment with the word STOP

Support SteemitBoard's project! Vote for its witness and get one more award!