/fob-2020

Code and documentation for the London Blockchain Labs 2020 Future of Blockchain project.

Primary LanguageJavaScript

Interfaces:

./vehicle-registry/

Steps to including DID into VehicleRegistry.sol (Already implemented, this is just explanation)

  1. Implement a DID smart contract, based on IoTeX's implementation here: https://github.com/iotexproject/iotex-did/blob/master/smartcontracts/contracts/IoTeXDID.sol

    • In addition to ALL of the above DID methods, add a method getDocumentUriFromIMEI(string IMEI) to get the location of the DID document based only on the IMEI of the device
    • For this to work it means we also have an additional mapping(string => string) where string1 is an IMEI and string2 is a DID id string e.g. did:io:0x2323....4039
    • Note, we should store the DID document on Arweave, for the sake of the challenge prize.
  2. Add an additional field to the DID document called "creator", which is a DID string pointing to the owner of the device, so that we can slash them when needed.

    • This means that one owner can have multiple devices pointing to it, e.g. in the case where a person has multiple cars, or multiple ships in his/her fleet
  3. How to slash?

    • When we receive data from a device (either through streaming, or through pinging the S3 bucket), we get the GPS coordinates, and convert them to a turfJS point
    • We then query the JurisdictionRegistry.sol to get the polygon boundaries
    • We pass the point, and the polygon boundaries into the enclave which checks whether the point is in the polygon
    • If it isn't we don't need to do anything. If it is, we get the device's IMEI (it would be passed to us in the data), then we use that IMEI to get the DID document as described by the getDocumentUriFromIMEI() smart contract method described in point number 1. We read creator field from the DID document (which is stored on Arweave), and then make a slash() smart contract call with that creator's DID.
  • To begin with, the DID document should be in the format:

      {
        "@context": "https://w3id.org/did/v1",
        "created": "2018-02-08T16:02:20Z",
        "entity": "Individual"
        "creator": "did:io:0x5576E95935366Ebd2637D9171E4C92e60598be10",
        "imei": "3489075349087539087894"
      }
    
  • What does each field mean?:

     * "@context": always the same as above. 
     * "created": timestamp of when the DID is created. 
     * "entity": can be "device", "company:company name", or "individual". 
     * "creator": optional, only used if its a device DID. 
     * "imei": optional, only use if its a pebble tracker
    

How does VehicleRegistry.sol work?

  • The contract method names are self explanatory. The main things to note about the contract:
    • One "owner" can have multiple vehicles assigned to them. Each vehicle has its own stake amount and expiry date, which means each vehicle can be penalised individually.
    • The contract does not really care about addresses, it works with DIDs. DIDs should be passed in as a string in the format, for example, did:io:0x5576E95935366Ebd2637D9171E4C92e60598be10
    • Right now for testing purposes the lockTime input variable during registration is in minutes as its easy to test that staking works correctly then. Once the web forms are complete we can easily extend to support multiple units e.g. seconds, minutes and days

Requirements

02/02/2020: We need a web form to register a PERSON to give them a DID and store the DID document on Arweave (Leo). 02/02/2020: We need a web form to register a DEVICE to give it a DID and store the DID document on Arweave (Leo). 02/02/2020: We need a web form to register VEHICLES using VehicleRegistry.sol (Tony?).

./jurisdiction-registry/

Governments register MPA boundaries

./node-cloud/

WHO? Runs Cloud Node program (or within enclave?)

  • Fetch current boundaries (query smart contract)

  • Check for new data into S3 cloud bucket every minute

  • Check to see if points are within MPA boundaries (eventually trusted script)

    • If TRUE:
      • Submit transaction slashing that vessel's stake
      • Set bool CleanCatch = False (?). This means that the Node service has private keys to sign tx. Who is administering this? Etc?
  • Note: This requires trust in a centralized authority. This process could be executed inside a secure enclave - and potentially replicated so each jurisdiction

./

Externally-owned accounts / Roles:

Government

Government Root Account

  • Constructs Jurisdiction contracts
    • Registers boundaries
  • Registers and deregisters border officials

✅ Hard code registration

Border Officials EOAs

✅ Human interface

  • View complete list of shipments in country
  • View appropriate container metadata

Manufacturer

✅ Human interface

  • Submit verification that shipment is ok

Buyer

✅ Human interface

  • Submit verification that shipment was received ok

Shipper

Container

✅ Machine interface

  • Register ownership of device?

NodeJS

// on tracker ping:


// fetch data from Redis - or stream





  // Check which jurisdiction the tracker is in

  // Check which jurisdiction tracker is registered in on-chain

  // if different:
    // Revoke access to prior jurisdiction
    // Grant access to current jurisdiction
    // AND execute enter(jurisdiction);
  // Check if tracker is still in that jurisdiction
    // If yes:

    // Else:
      // Check if tracker is inside another jurisdiction

Solidity

contract Tracker {

  address currentJurisdiction; // < contract address

  construction () {

    // register DID on iotex registry with msg.sender as owner
  }




  crossBorder(_departingJurisdiction, _enteringJurisdiction) {


    // revoke _departingJurisdiction officers access to location information


    // pay _enteringJurisdiction money.
    // grant _enteringJurisdiction officers access to location information


    // update currentJurisdiction


  }


}



contract Jurisdiction {
  boundaries;
  uint importTaxPct;
  did; // did:io:_contractaddress_

  struct Officer {
    address,


  }
  mapping (address => Officer) officers;



  constructor (_boundaries) {
    // register DID with boundaries
    //
  }



  // list of border officers
  function registerOfficer () {

  }

  function removeOfficer () {

  }

  function updateBoundaries (_newBoundaries) {
    // replace boundaries with new boundaries
  }






  function enterJurisdiction (_trackerId) payable {

    // confirm signatures
    // accept payment ...


  }


  function departJurisdiction (_trackerId) {

  }



}



contract JurisdictionRegistry {

}

DIDs

// Tracker




// Jurisdiction

{
    "@context": "https://w3id.org/did/v1",
    "id": "did:io:<<Government's wallet address>>",
    "publicKey": [{
        "id": "did:io:<<public key>>#keys-1",
        "type": "RsaVerificationKey2018",
        "controller": "did:io:0x56d0B5eD3D525332F00C9BC938f93598ab16AAA7",
        "publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n" }],
    "authentication": [{
        "type": "RsaSignatureAuthentication2018",
        "publicKey": "did:io:0x5576E95935366Ebd2637D9171E4C92e60598be10#keys-1" }],
    "service": [{
        "id": "did:io:0x88C36867cffB66197812a9385A038cc6Dd75244b;fetch_boundaries",
        "type": "FetchBoundaries",
        "serviceEndpoint": "https://gateway.ipfs.io/ipfs/QmTeW79w7QQ6Npa3b1d5tANreCDxF2iDaAPsDvW6KtLmfB/" }],
        // a signed hash of the boundaries for verification in SGX enclave.
    "created": "2018-02-08T16:03:00Z",
    "proof": {
        "type": "LinkedDataSignature2015",
        "created": "2018-02-08T16:02:20Z",
        "creator": "did:io:0x5576E95935366Ebd2637D9171E4C92e60598be10#keys-1",
        "signatureValue": "QNB13Y7Q9...1tzjn4w=="
    }
}    


//

Rust

// In SGX enclave on the cloud:


// point in polygon {
  // confirm validity of jurisdictional boundaries (verify signed hash)\
  // confirm validity of tracker location (verify signed coordinates)
  // calculate if point in polygon

}


// Obvs not rust but ...
function toBeChecked (_trackerId, _jurisdiction)
  returns (bool performCheck_) {
  // If temperature has stayed below max
  // and
  // trackers[_trackerId].Value > x
  // and
  // No controlled ingredients
    return False;
  } Else {
    return True;
  }
}