router
package provides core routing functions. You include the router
package as an ELPS package. E.g.,init
which is called both on a substrate upgrade and on an over-the-air (phylum) update. This is where you register migration and initialization logic.route-success
and route-failure
which are used to construct success and failure messages for the shiroclient. These functions take a single argument which is returned to shiroclient either as a successful response, or as an error. These functions merely construct the properly formatted response, and do not early abort from the function. The result of evaluating the registered handler function is returned to shiroclient, and that result should be a message constructed by route-success
or route-failures
.defendpoint
function.(defun register-endpoint (endpoint arg-names handle-fun))
takes an endpoint name, list of argument names, and a handler function. defendpoint
is a macro which calls register-endpoint
to register a JSON-RPC handler with method name endpoint
and arguments arg-names
, and callback handler-fun
.statedb
or sidedb
packages. As in HLF, this data is only persisted subject to the standard transaction endorsement and commitment flow.statedb:put
). This is in contrast to vanilla HLF which does not.statedb
package provides helpers to read and write data to the HLF state database.(statedb:get-bytes k)
takes a string key k
and returns the stored bytes for that key from the HLF state database. ()
is returned if there is no value stored for that key.(statedb:get k)
takes a string key k
and calls statedb:get-bytes
, but then deserializes the bytes into an ELPS object by calling the statedb:deserialize
function.(statedb:put-bytes k v)
takes a string key k
and bytes v
and stores v
under k
in the HLF state database.(statedb:put k v)
takes a string key k
and ELPS object v
, serializes the object by calling the statedb:serialize
function and then calls statedb:put-bytes
.(statedb:del k)
takes a string key k
and deletes any value in the statedb for this key.(statedb:serialize v)
is the serialization function for the statedb
package. It converts an elps object into a bytes (presently as JSON bytes).(statedb:deserialize b)
is the deserialize function for the statedb
package. It converts bytes to an elps object (presently from JSON bytes).set
that takes an object obj
which has a propert key
and val
. This endpoint then stores val
in the statedb under key key
, and returns a success message with the data stored under a key data
:(statedb:range-bytes fn z start end)
performs a range query against the state database, starting from key start
(inclusive) and ending at key end
(exclusive). fn
is a reduce function with signature (acc curr-key curr-val)
, and z
is the initial value of acc
. acc
is the accumulator parameter in the reduce, curr-key
is the current key being ranged over, and curr-val
is the value (bytes) for that key.range
works the same as range-bytes
, but calls deserialize
on the curr-val
bytes.sidedb
package provides functions for persisting data to HLF a common "private data collection" (pdc) [3] with name private
. The network must be configured with this collection enabled.statedb
, however this data is persisted to the pdc with name private
.private
package provides functions for persisting and manipulating private data that cannot be stored directly on the blockchain .(defun put-hashed (table nchar key val)
puts (key, val) in the given table with buckets labeled by the given number nchar
of hex characters of key hash. if val is nil, any association for the given key is removed. an empty bucket will still contain a salt and take up space. This data is persisted in the sidedb
and is used to avoid persisting hashes of private data in the state database. This function is helpful for storing data with a private key in the private database, where a direct call to sidedb:put
with that key would insecurely store the hash of the key on the state database.(defun get-hashed (table nchar key)
retrieves the value associated with the given key in the given table with buckets labelled by the given number of hex characters of key hash.mxf
, or message transform, to take messages and apply certain transformations of specific fields, to generate an "encoded" message.context_path
(defined in elpspath) that is on the context object. A transform specifies paths private_paths
in elpspath notation that are passed to the compression and encryption algorithms, where a new encoded message is generated that removes these referenced private paths from the context object. The compressed and encrypted fields are included in a separate section of the encoded message that is distinct from the original payload.mxf
uses certain paths profile_paths
on the context object that uniquely identify a data subject and their encryption key. These paths are expressed in elpspath notation, and are used to construct a Data Subject Profile (DSP). The DSP is an object that uniquely identifies the data subject and is stored in the sidedb
. All data subjects have a unique ID called the DSID. The DSP is used by mxf
to lookup a a DSID, which in turn is used to look up a Data Subject Record (DSR). The DSR is an object that includes a DSID, DSP, and a DSK (data subject key), and is also stored in the sidedb
. The DSK is used in all AES-256 confirmations for a data subject (along with a unique IV generated for each operation). If the DSR does not exist, then a new DSR is created, along with a new random key.mxf
to encode the context object using the above transforms:mxf
will decode this example encoded message into the original example context object.(defun mxf-encode (msg transforms)
mxf-encode applies transformations to a message, generating DSR when necessary.(defun mxf-decode (enc)
mxf-decode uses the private DB to decode a message that was previously encoded using mxf-encode
.(defun get-mxf (key)
retrieves an encoded message from the state database and decodes it.(defun put-mxf (key msg transforms)
encodes and places the encoded message into the state database. It adds bookkeeping to track where DSD is placed, to efficiently support data export.(defun mxf-purge-dsid (dsid)
removes all data associated with a DSID by destroying the associated DSR from the sidedb.(defun mxf-purge-profile (profile)
Removes all data associated with a data subject profile (DSP).(defun mxf-profile-keys (profile)
Returns the statedb keys for the given profile (DSP). This function is used to lookup all the data associated with a data subject.mxf-decode
) a message that was previously encrypted by the smart contract (e.g., via private_encode
). Called by the shiroclient-sdk-go private
library.mxf-encode
) a message using a transform. This is useful for GDPR compliance. Only transient data should be passed to this endpoint via a single field mxf
. Transient data is not placed on the blockchain. This TX may be committed in the case where we are generating new DSRs. Called by the shiroclient-sdk-go private
library.put-mxf
. The transient field private_update
is used to look up a key
path
and value
, where key
contains an mxf-encoded object, path
is an elpspath
and value
is the updated value.cc
package provides the basic building blocks for interacting with HLF and performing basic smart contract operations.(defun force-no-commit-tx ()
forces a transaction to not be committed by including information in the transaction response that signals to shiroclient
to skip commitment.(defun substrate-version()
Returns the version string of substrate.(defun add-date (date-or-timestamp num-years num-months num-days)
Adds the specified years, months, or days to a date or timestamp.(defun add-days (date-or-timestamp num-days)
Adds the specified days to a date or timestamp.(defun add-months (date-or-timestamp num-months)
Adds the specified months to a date or timestamp.(defun add-seconds (date-or-timestamp num-seconds)
Adds the specified seconds to a date or timestamp.(defun add-years (date-or-timestamp num-year)
Adds the specified years to a date or timestamp.(defun now ()
Return an RFC3339 [5] timestamp for the current time in UTC. The time is extracted from transient data provided by shiroclient.(defun date-now ())
Current time in YYYY-MM-DD
format.(defun parse-date (date)
Parse a date string in YYYY-MM-DD
format into a date object.(defun parse-timestamp (ts)
Parse a timestamp string in RFC3339 format into a timestamp object.(defun timestamp (ts)
Convert a timestamp object into a string (RFC3339).(defun timestamp-unix (ts)
Convert a timestamp into unix epoch time and output as a hex string.(defun ymd-between-dates (date-1 date-2)
Returns the difference between 2 dates provided for each date component.(defun auth-claims (token &key no-verify)
Parses a JWT token
and returns a sorted map of claims. Presently only :no-verify true
is supported, and token authentication must occur off-chain.(defun csprng-init (seed-bytes)
Initialize a (transaction scope) HKDF with the given random seed bytes. These random bytes are normally passed as transient data. Uses HMAC-SHA512 (RFC 5869) [4].(defun csprng-generate (num-bytes)
Generate num-bytes
of pseudo random bytes using the initialized csprng
.num-bytes
are requested and not enough seed-bytes
. In this case, the function will throw an error.(defun transient-get (key)
Retrieve data for a specific key
, from transient data passed within a JSON object (typically via the shiroclinet SDK). Transient data is data made available within a chaincode transaction, but is not persisted to the blockchain data structures. [3] Keys beginning with $
are reserved for internal substrate use.(defun tx-id ()
Return a string of the HLF transaction ID.(defun set-tx-metadata (key val)
Set metadata with string key key
and string value val
on the transaction context.(defun get-tx-metadata (key val)
Get metadata with string key key
from the transaction context.(defun errorf (fields msg)
Log message msg
at level=error
with map of structured fields fields
.(defun infof (fields msg)
Log message msg
at level=info
with map of structured fields fields
.(defun warnf (fields msg)
Log message msg
at level=warn
with map of structured fields fields
.(defun (set-log-field key val)
Attach structured log fields to the logger, with field key string key
and field value string val
.(defun log-metrics ()
Info log storage related metrics (e.g., numbers of keys written and read to).(defun encode (data)
Return a base64 encoded string of data
, where data
is type byte or string.(defun decode (data)
Base64 decode string data
and return decoded bytes.(defun encode (data)
Return a hex encoded string of data
, where data
is type byte or string.(defun decode (data)
Hex decode string data
and return decoded bytes.(defun sha512-digest (data)
Return the sha512
digest bytes of string or bytes data
.(defun sha256-digest (data)
Return the sha256
digest bytes of string or bytes data
.jq
.(defun get-path (obj path)
Query elpspath path
on sorted-map obj
and return the resulting value.(defun set-path! (obj path val)
Query elpspath path
on sorted-map obj
and set the value at that path to val
.(defun version ()
Return a version string of handlebars.(defun render (tpl ctx)
Parse and evaluate handlebars on string template tpl
with sorted-map context ctx
and return the resulting string.(defun must-parse (tpl)
Parse handlebars string template tpl
and throw a 'handlebars-parse
error if the template is invalid.(defun libname ()
Return the string name of the underlying handlebars library.appctrl
package.(use-package 'appctrl)
(defun get-prop (key)
Retrieves a value for a property name.(defun set-prop (key val)
Sets a value for a key.distinct:
then a separate statedb key is used for the property, to avoid MVCC conflicts across property updates.set_app_control_property
and get_app_control_property
are automatically registered, and call set-prop
and get-prop
respectively.