_images/database.png

Querying

Assets and contracts deployed on the ledger be queried for specific information regarding their state, history of all previous states, and all participants involved in their history.

Integrating Private State

The private state file contains values to use with Commitment Schemes.

To check whether a private state file matches the locals in a contract:

$ uplink scripts compile contracts/locals.s -s contracts/locals_state.json

To commit a private state file to the local db for a specific contract and account:

$ uplink data commit contracts/locals_state.json <contract_addr> <account_addr>

Private state allows two parties to load some private values shared between them into a contract. These values can then have certain operations applied to them by a contract. After a contract is finalized, the creator of the contract can then reveal a parameter of the commitment process, which allows other parties to verify there initial values were the same.

SQL Queries over Ledger

If Uplink users are running a relational database backend, they can query the state of the ledger using a SQL language by sending a query string to the RPC interface, receiving results in the form of either Account, Asset, or Contract values. The syntax for querying the ledger is familiar:

SELECT transactions WHERE origin='highStreetBankAddress' AND txtype="Transfer";

This language allows the users to query the state of the uplink ledger similar to the way in which one would query a relational database comprised of tables. However, since the Uplink ledger is a layer on top of traditional database architectures, the way users interact with and the internal, higher level representation of these ledger values are not relational in nature. In order to store Uplink ledger data in a relational database, a relational schema must be derived from the higher level data structures Uplink uses internally.

The resulting schema is complex and results in a non-intuitive interface through which to query data. Instead of requiring users to learn the underlying schema that Uplink stores the ledger data in, a SQL-like query language has been implemented such that users can perform aggregate queries over ledger values in and intuitive and familiar style.

Query strings in this language are of the form:

query
  : QUERY <ledgervalue>;
  | QUERY <ledgervalue> WHERE <whereclause>;

ledgervalue
  : accounts
  | assets
  | contracts
  | transactions

whereclause
  : <condition> AND <whereclause>
  | <condition> OR <whereclase>
  | <condition>

condition
  : <columnname> =  <columnvalue>
  | <columnname> >  <columnvalue>
  | <columnname> >= <columnvalue>
  | <columnname> <  <columnvalue>
  | <columnname> <= <columnvalue>

Where column names and column values are specified in the tables below.

Each ledger value has fields that can be specified in the conditional part of the query string:

Queryable Fields

Accounts:

Field Type
address Address
timezone Text

Assets:

Field Type
name Text
issuer Address
issuedOn Int
supply Int
reference Text
assettype Text
address Address
holder Address

Contracts:

Field Type
timestamp Int (POSIX time)
state Text
owner Address
address Address

Transactions:

Field Type
txtype Text
origin Address
timestamp Int (POSIX time)

Examples

To query all assets where account address ‘H1tbrEKWGpbPjSeG856kz2DjViCwMU3qTw3i1PqCLz65’ has holdings:

QUERY assets WHERE holder='H1tbrEKWGpbPjSeG856kz2DjViCwMU3qTw3i1PqCLz65';

To query all transfer transactions submitted by account address ‘H1tbrEKWGpbPjSeG856kz2DjViCwMU3qTw3i1PqCLz65’:

Query transactions WHERE origin='H1tbrEKWGpbPjSeG856kz2DjViCwMU3qTw3i1PqCLz65' AND txtype="Transfer";

To query all contracts created between “Sat, 20 Jan 2018 00:00:00 GMT” and “Mon, 22 Jan 2018 12:00:00 GMT” that are currently in their “initial” state:

QUERY contracts WHERE timestamp > 1516406400000000 AND timestamp < 1516622400000000 AND state = "initial";

Querying Ledger Database

Currently, there are two interface through which to query the ledger values from the database using this SQL-like query language: the RPC interface and the uplink console.

The uplink command line exposes two ways to get data:

Get a contract, asset, or account by address

$ uplink data get <address>

Dumping all contracts, assets, accounts, and blocks

$ uplink data list

Exporting to SQL

To export ledger data to SQL, a node must be run using a Postgres backend. Once the node joins the Uplink network, it will request the first block in the ledger, and subsequently all other blocks in the chain, consecutively applying the block transaction to the ledger state and writing the resulting state to the Postgres database. After the node has synced it’s local state with the network, the ledger data will be stored in the Postgres database and can be read by any user with the proper permissions on the local machine.

Currently there is no way to export ledger data to SQL from a LevelDB database other than to boot an Uplink node with a Postgres backend specified, and syncing with the network.

Future versions of Uplink will support the specification of a “boot” database, a database from which to load the ledger state, as well as the “working database”, the database to which the node will write both old and new ledger data. By default the “boot” database is the same as the “working database”.

Exporting Blocks

Uplink supports data migration of the entire ledger state into either JSON or XML files for backup and migration. By default, data is exported in JSON format.

Exporting to JSON

To export block history of Uplink as JSON, run:

$ uplink data export blocks backup.json
$ uplink data export blocks -f JSON backup.json

Example file contents of backup.json:

[
    {
        "transactions": [],
        "header": {
            "origin": "11111111111111111111111111111111",
            "consensus": {
                "blockPeriod": 1000000,
                "minTxs": 1,
                "blockGenLimit": 1,
                "validatorSet": [
                    "vLKc7J2aZEsXzRnxAcZ7tw2kRKKr69ffzTDjRU5fpRh",
                    "32zr5nyqWfguKBWEWW6SbB9NnciR8yU9rTz4sRwRmK4S",
                    "4nn4beQTAT1vo44GDWq97KARVtAg5kN6iDctyPhDnUbv",
                    "74Zh9ieinY2fozrvX8cMK2x3hqgP3oXLnCbCceuQZFDY",
                    "7fpCnRDgm8B4VdjRk1jvskhNoAPbZ4S5eMD2TF8sytWF",
                    "BHAZvsLnFgvmYkaJQpQwcZZAALFxxqttKQtqompDb426",
                    "E1qLYBKYgNJerohFhGuBC7q2kBQ7sVGRopn6gNwaBqQf",
                    "F8XUEiSUDKRhG6Srfft7zB4n8KWEZ6G3YnRg3F5MetVU",
                    "H8L7BGsbLZVkCytBC35SA6FesTP1Y1b8neydvVQ4FY7h",
                    "Hocqmrjip3MwyGuTXhfQpUPMhpMZkapo6DnWUDtuuVfu",
                    "HyP48is6eiQP1QURvvbVhAFABpP3FKPskFy4qdDCgjKh"
                ],
                "threshold": 1,
                "signerLimit": 1
            },
            "merkleRoot": "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
            "prevHash": "c6fdd7a7f70862b36a26ccd14752268061e98103299b28fe7763bd9629926f4b",
            "timestamp": 1231006505
        },
        "signatures": [],
        "index": 0
    },
    ...

Exporting to XML

To export the current ledger state to XML run:

$ uplink data export blocks -f XML backup.xml

Example file contents of backup.xml:

<?xml version="1.0" encoding="UTF-8"?>
<blocks>
    <block index="0">
        <signatures/>
        <header origin="Address &quot;11111111111111111111111111111111&quot;" prevHash="c6fdd7a7f70862b36a26ccd14752268061e98103299b28fe7763bd9629926f4b" merkleRoot="&quot;a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a&quot;" timestamp="1231006505">
            <consensus validatorSet="fromList [Address &quot;vLKc7J2aZEsXzRnxAcZ7tw2kRKKr69ffzTDjRU5fpRh&quot;,Address &quot;32zr5nyqWfguKBWEWW6SbB9NnciR8yU9rTz4sRwRmK4S&quot;,Address &quot;4nn4beQTAT1vo44GDWq97KARVtAg5kN6iDctyPhDnUbv&quot;,Address &quot;74Zh9ieinY2fozrvX8cMK2x3hqgP3oXLnCbCceuQZFDY&quot;,Address &quot;7fpCnRDgm8B4VdjRk1jvskhNoAPbZ4S5eMD2TF8sytWF&quot;,Address &quot;BHAZvsLnFgvmYkaJQpQwcZZAALFxxqttKQtqompDb426&quot;,Address &quot;E1qLYBKYgNJerohFhGuBC7q2kBQ7sVGRopn6gNwaBqQf&quot;,Address &quot;F8XUEiSUDKRhG6Srfft7zB4n8KWEZ6G3YnRg3F5MetVU&quot;,Address &quot;H8L7BGsbLZVkCytBC35SA6FesTP1Y1b8neydvVQ4FY7h&quot;,Address &quot;Hocqmrjip3MwyGuTXhfQpUPMhpMZkapo6DnWUDtuuVfu&quot;,Address &quot;HyP48is6eiQP1QURvvbVhAFABpP3FKPskFy4qdDCgjKh&quot;]" blockPeriod="1000000" blockGenLimit="1" blockSignLimit="1" threshold="1" minTxs="1"/>
        </header>
        <transactions/>
    </block>
    <block index="1">
        <signatures>
            <BlockSignature signature="&quot;AE02MjcwNjM5NjUyNDI3OTg2NjA5MjMwMzQ3MTg3MTMxMTkwNzQyMzQxNjE5OTg4MTM1NTc0MTIxMTMzODQxMDU2MjAxNTU0MTg2MTgyMDoATTE0ODEyNDUxMTIyNjE2MDY2NzM0MzUzODMxNjU5ODk4MDEwODQyOTg0NDc2MDU1Nzk3MjkzNjA5MzAxNjM3MjExMTg2MTk2NDg0MDUw&quot;" signerAddr="F8XUEiSUDKRhG6Srfft7zB4n8KWEZ6G3YnRg3F5MetVU"/>
        </signatures>
        <header origin="Address &quot;F8XUEiSUDKRhG6Srfft7zB4n8KWEZ6G3YnRg3F5MetVU&quot;" prevHash="507c05e0904838773bdbdd8c37dfd30c18350695cd0279f74f6f906e5a935c7d" merkleRoot="&quot;69de24b50899e1333a5d2bccd55eb190ed88ea110efcbed7726216c372881f8d&quot;" timestamp="1530283413675198">
            <consensus validatorSet="fromList [Address &quot;vLKc7J2aZEsXzRnxAcZ7tw2kRKKr69ffzTDjRU5fpRh&quot;,Address &quot;32zr5nyqWfguKBWEWW6SbB9NnciR8yU9rTz4sRwRmK4S&quot;,Address &quot;4nn4beQTAT1vo44GDWq97KARVtAg5kN6iDctyPhDnUbv&quot;,Address &quot;74Zh9ieinY2fozrvX8cMK2x3hqgP3oXLnCbCceuQZFDY&quot;,Address &quot;7fpCnRDgm8B4VdjRk1jvskhNoAPbZ4S5eMD2TF8sytWF&quot;,Address &quot;BHAZvsLnFgvmYkaJQpQwcZZAALFxxqttKQtqompDb426&quot;,Address &quot;E1qLYBKYgNJerohFhGuBC7q2kBQ7sVGRopn6gNwaBqQf&quot;,Address &quot;F8XUEiSUDKRhG6Srfft7zB4n8KWEZ6G3YnRg3F5MetVU&quot;,Address &quot;H8L7BGsbLZVkCytBC35SA6FesTP1Y1b8neydvVQ4FY7h&quot;,Address &quot;Hocqmrjip3MwyGuTXhfQpUPMhpMZkapo6DnWUDtuuVfu&quot;,Address &quot;HyP48is6eiQP1QURvvbVhAFABpP3FKPskFy4qdDCgjKh&quot;]" blockPeriod="1000000" blockGenLimit="1" blockSignLimit="1" threshold="1" minTxs="1"/>
        </header>
        <transactions>
            <transaction signature="AEw0MjI0NzY5NTI0NjI0ODUwMzA2NTQ5NDQ1NzI5Mzg2NDE0MDA2OTIzNDUxNzEwNjkzMzA5MzM3NzIwNjE2ODYyNTI4NTYyOTk5NzI5OgBNMjM0MDQ3OTc3NjgzNjgxNDYyMTAxNjk3OTYwMDc1Mjc3Mjg5ODQzMDc5NDkxMTAwNjYxMTAzMjMxNjMyMjkzNTIyNjU5NzQzOTYzMjg=" origin="Address &quot;HkKThPbP4ozjpsSLBfPCwTrau649biCfkAJ1H5kQ5sgA&quot;">
                <CreateAccount pubkey="&quot;aee8c3bc44d4c4629b17a35269fede7bcac1740fd474974b8d221e6152d8638b2f9da55fa52ac98f4d4f65ab0521e626629ffea5b9ba32682c7c91a4ee86fd51&quot;" timezone="&quot;GMT&quot;"/>
            </transaction>
        </transactions>
    </block>
    ...

Exporting Ledger

The current ledger state can be exported as JSON with the command

$ uplink data export ledger ledger.json

Example file contents of ledger.json

{
  "accounts": {
      "2KBXteKPCtNYXU1YVyGBhbGYDqkp2kaQ7Ki9EdQrBDuB": {
          "publicKey": "5a02654a4436361021efbe8a116cf2841cf147455f2be6064f7a7a62c507c1c7d3ca964b67901e40f31891330c538c02189b98c5584bff9b54af30561039047f",
          "address": "2KBXteKPCtNYXU1YVyGBhbGYDqkp2kaQ7Ki9EdQrBDuB",
          "metadata": {},
          "timezone": "GMT"
      },
      ...
  "contracts": {
      "3Levi98i4JAbsNt9v5TD3ST1xPrQAZGWbYzWCi8F9kN8": {
          "script": "\ntransition initial -> circulated1;\ntransition circulated1 -> transferred1;\ntransition transferred1 -> circulated2;\ntransition ..."
          "state": "terminal",
          "address": "3Levi98i4JAbsNt9v5TD3ST1xPrQAZGWbYzWCi8F9kN8",
          "owner": "2a852K3gWGafDSbu1tfCkLhRvnA6Q6h3zy12K4WC7ZeG",
          "storage": {},
          "localStorage": {},
          "methods": [
              "circulate1",
              "transfer1",
              "circulate2",
              "transfer2"
          ],
          "localStorageVars": [],
          "timestamp": 1530517239877166
      },
      ...
  "assets": {
      "A43CfPipEjw4bturK4ZaTHsqYRn13jBhwMxKrNk61m3z": {
          "holdings": {
              "2a852K3gWGafDSbu1tfCkLhRvnA6Q6h3zy12K4WC7ZeG": 99900000,
              "AjAGix186NgqD9kizoigbVKbLhXfYsBB2F2S4bswjgbC": 100000
          },
          "issuedOn": 1530517305331732,
          "supply": 0,
          "reference": "Token",
          "address": "A43CfPipEjw4bturK4ZaTHsqYRn13jBhwMxKrNk61m3z",
          "name": "protected",
          "metadata": {},
          "assetType": {
              "tag": "Fractional",
              "contents": 2
          },
          "issuer": "2a852K3gWGafDSbu1tfCkLhRvnA6Q6h3zy12K4WC7ZeG"
      },
      ...
}

This feature is supported in addition to exporting the block data because it is possible, for testing purposes, to load a snapshotted ledger state as the state of an uplink node from a JSON encoded file.