Technical Details
This information is documented in case you want to develop your own general-purpose TinyChain client, or if you need to do an in-depth security or risk analysis.
Data description
TinyChain exposes a JSON API over HTTP, and treats a subset of JSON as a Turing-complete application language. For example, this is a function to convert meters into feet:
Obviously writing this by hand gets unwieldy very quickly, which is why the Python client is provided. Here's the same function defined using the Python client:
Replication
A TinyChain cluster uses a variation on fast Byzantine multi-Paxos consensus.
The life of a replica R of a cluster C is:
Host loads cluster config
If any peer is hosting a cluster at the same path, a replication request is sent, and the state of R is updated to match the state of C; otherwise, R is assumed to be the latest state of C
R will handle transaction requests for C according to the flow below until its host is shut down or it attempts to commit a transaction and fails
If R attempts to commit a transaction and fails, it will stop accepting requests and attempt to re-join C by starting from step 1. above (assuming that automatic restarts are configured with systemd)
The flow of operations within a single transaction is:
A replica host R of cluster C with N total replicas receives a new transaction request T
R claims ownership of the transaction
For
PUT
andDELETE
operations, the request T itself is replicated; for user-definedGET
andPOST
requests, write operations which are part of T are replicated to all other hosts in CEach dependent cluster Cx receives a request Tx, claims leadership of Tx, and replicates Tx to all hosts in Cx
If any host responds with error 409: conflict, the transaction is rolled back and error 409 is returned to the end-user
Otherwise, if at least (N / 2) + 1 hosts in each participating cluster respond with success, each cluster C removes the unsuccessful hosts from its replica set, commits the transaction, and responds to the end-user
Otherwise, the transaction is rolled back and an error is returned to the end-user
Important note: the TinyChain protocol does not support trustless replication. Do not allow untrusted replicas to join your cluster. A single malicious replica can significantly degrade performance, or even halt all updates entirely, by creating extra work to reach consensus; it can also report false information to your clients and the network as a whole.
Authentication
TinyChain uses recursive JSON web tokens provided by the rjwt library. Each TinyChain host which handles part of a transaction must validate the auth token of the incoming request, sign it with its own private key, and forward it to any downstream dependencies. Note the unusual security consideration of a recursive token: a downstream dependency receives all of the upstream tokens, and therefore is authorized to take any action which an upstream dependency is authorized to take. For this reason, it's very important to use only a minimal scope to authenticate the end-user, and grant further scopes as narrowly as possible.
Life of a transaction
Example:
user@example.com
initiates the transaction by sending a request toretailer.com
, with an auth token signed byexample.com
whose scopes limit its use to the intended actionretailer.com
claims ownership of the transaction by creating a new, signed request token which includes the original tokenretailer.com
sends a request tobank.com
to debit $20 from the user's accountretailer.com
sends a request tofactory.com
to manufacture 1 widgetfactory.com
sends a request tobank.com
to debit $10 fromretailer.com
's accountfactory.com
sends a request toshipping.com
to schedule a shipment to the user's address, and chargeretailer.com
shipping.com
sends a request tobank.com
to debit $5 fromretailer.com
's account
Requests at the same indentation level above are executed concurrently, after validating the incoming request token. Acceptance of a request with transaction ID X forbids acceptance of any other request with transaction ID X, unless they share the same owner.
Note that this is only the case in a mutation (a write transaction). A read-only transaction does not need to perform any explicit synchronization with the transaction owner, only to lock the given transaction ID.
The concurrency control flow of this sequence of operations, starting from transaction number (X - 1) is:
Client initiates transaction X
Service endpoint validates auth token
Service endpoint claims transaction X, becoming the transaction owner
Service endpoint executes requested operation
Dependency receives request
Dependency validates auth token
If the dependency is part of a different cluser than the transaction owner, it notifies the owner of its participation (this is necessary to synchronize dependencies further downstream)
Dependency executes requested operation and replies to the transaction owner
Transaction owner notifies dependencies of success, updating their latest committed transaction to X
Transaction owner updates its latest committed transaction to X
Transaction owner replies to the client
This functionality is implemented automatically for any service using the TinyChain host software.
Important note: this cross-service consensus algorithm trusts each service to a) recover from a crash without losing state, and b) communicate that it has committed a transaction honestly and correctly. In other words, it is not a new and trustless protocol, but a new formalization of an existing ad-hoc procedure. An application which requires completely trustless transactions, like a distributed cryptocurrency, should use a single replicated cluster.
More information
If you need some technical details which are not listed on this page, you can check the internal documentation for TinyChain's host software at docs.rs/tinychain, or just Ask for help!
Last updated