Openchain data structures

Openchain relies on several data structures for communication between clients and servers. These data structures are a key part of the Openchain API.

These data structures are serialized and deserialized using Protocol Buffers.

Schema

The full schema is the following:

syntax = "proto3";

package Openchain;

message RecordValue {
    bytes data = 1;
}

message Record {
    bytes key = 1;
    RecordValue value = 2;
    bytes version = 3;
}

message Mutation {
    bytes namespace = 1;
    repeated Record records = 2;
    bytes metadata = 3;
}

message Transaction {
    bytes mutation = 1;
    int64 timestamp = 2;
    bytes transaction_metadata = 3;
}

Note

The schema uses the version 3 of Protocol Buffers.

Record

A record object represents the intent to modify the value of a record in the data store. The key, value and version of a record can be any arbitrary byte string.

message Record {
    bytes key = 1;
    RecordValue value = 2;
    bytes version = 3;
}
  • key: A value that uniquely identifies the record to modify.
  • value: The new value that the record should have after update. If it is unspecified, the record version is checked, but no update is made to the value.
  • version: The last version of the record being updated. Every modification of the record will cause the version to change. If the version specified doesn’t match the actual version in the data store, then the update fails.

A record that has never been set has a value and version both equal to an empty byte string.

Check-only records

If a record object has a null value field, the record object is called a check-only record, and does not cause a mutation to the record. It however expresses the requirement that the record (as represented by the key field) must have the version specified in the version field of the record object. If the versions don’t match, the whole mutation fails to apply.

This provides a way to ensure that a given record has not been modified between the moment the transaction was created and the moment it gets validated, even if the record doesn’t have to be modified.

Mutation

A mutation is a set of records atomically modifying the state of the data. They are typically generated by a client, signed, then sent to the validator along with the signatures.

message Mutation {
    bytes namespace = 1;
    repeated Record records = 2;
    bytes metadata = 3;
}
  • namespace: The namespace under which the records live. Generally, each instance of Openchain has its own namespace.
  • records: A set of records to be modified atomically by this mutation. Each record is identified by its key. The version of each record in the mutation has to match the versions at the current time. If any version mismatches, then the entire mutation fails to apply. Records with an unspecified value don’t cause updates, but their versions still have to match for the mutation to succeed.
  • metadata: Arbitrary metadata to be stored in the mutation.

The version of all updated records after a mutation becomes the hash of that mutation.

Transaction

A transaction is a wapper around a mutation.

message Transaction {
    bytes mutation = 1;
    int64 timestamp = 2;
    bytes transaction_metadata = 3;
}
  • mutation: The mutation applied by the transaction. It is represented as a byte string but deserialized according to the Mutation schema.
  • timestamp: A timestamp for the transaction.
  • transaction_metadata: Arbitrary metadata to be stored in the mutation. This will typically contain a digital signature of the mutation by the required parties.