---
# System prepended metadata

title: Logical Clocks
tags: [docs]

---

---
title: Logical Clocks
tags: docs
---

# Logical Clocks

## Single-writer-log

For the single-writer-log (SWL) structure, Mosaic adopts the log structure described in ThreadsDB protocol[^ThreadsDB-ipfs] as a logical clock for a single writer. Validity of the log relies on valid signature from the LogId (equated to PeerId).

    CodedLogNode(N) (encrypted w ServiceKey)
     |-Sig (signs cidEventNode+cidPrevLogNode)
     |-PubKey (ServiceKey, ReadKey) (optional)
     |-PrevLogNode
     |  |-Sig
     |  |...
     |-EventNode
        |-CodedBodyNode (encrypted w ContentKey)
        |  |-Body
        |-CodedEventHeaderNode (encrypted w ReadKey)
           |-ContentKey


Here the signature signs a payload `(cidEventNode, cidPrevLogNode)` with the private key of the PeerId. Any node who has the service key can traverse the log history. A node that has the read key can decrypt the header of the record, and therefor the content key to decrypt the body. See code-reference[^cbor-record].

Content, read and service keys are symmetric keys.
Content key is randomly generated for each body.
In a first simple model, read and service keys are constant over the lifetime of SWL. Service keys can be rotated, and the old service key can be included in the `PubKey` field of the logNode, such that the history remains traversable[^qn-rot-servicekey].

A Thread is a topic-based collection of single-writer-logs. Conventiently these SWLs can share a service key and read key across the logs.[^thread-def]

As the service key is not globally shared, we call SWL local. Logs are part of the IPFS MerkleForest but there is a priori no global consensus over the head of a log. In the next chapter, strings and rings will be described as contracts to govern references to the heads of logs within a global consensus state.

## Ethereum as a global clock

A single-chain blockchain as Ethereum creates a global clock with each ordered transaction moving the global state forward. For convenience the transactions are grouped in blocks, and the block number is a global clock for the global state maintained in the state trie.

## multiple global sub-clocks

[describe variations of systems with multiple sub-clocks; including but not limited to cosmos, polkadot, (Eth2 sortition), metachains, ava]

## multi-writer-logs

Smart contract code executed within the state of a global (sub-)clock can serve as a multi-writer-log tracking the head of a similar log structure^[TODO:specify]. New record entries are appended by a threshold (of) signature(s) of participants in the multi-writer-log.

By using a majority vote on a Byzantine Fault-Tolerant (BFT) substrate[^substrate-explainer], the multi-writer-log is BFT without introducing strong synchronicity requirements[^strong-synchronicity] among the multi-writer-log participants ^[ie. without reconstructing a new blockchain among the participants, eg. using Tendermint]. This allows a multi-writer-log to be much more lightweight than if it would be constructed from the networking layer up; leveraging the presence of the global (sub-)clock that is already present in a blockchain network.

Participants in a multi-writer-log can each use single-writer-logs to communicate among eachother by sharing a thread. Those SW-log-entries must be mergable (with a logical clock or CRDT, depending on the application). A multi-writer-log environment itself is not intended to be BFT.

# Simultaneity

To consistently interact between independent logs (SW or MW), we can construct merkle-clocks by exchanging data objects in an event-driven architecture[^exploration-is-it-a-merkle-clock]

# Random references

- [go-threads/cbor/record](https://github.com/textileio/go-threads/blob/v0.1.18/cbor/record.go#L41)

# Footnotes

[^ThreadsDB-ipfs]: [ThreadsDB paper version dec 2020](https://ipfs.io/ipfs/QmRjgbB5pTxUnoLFbXtDHs1ph5t5pUhRnYn1wFiYEpP5s1?filename=201912TextileThreads.pdf)

[^cbor-record]: A LogNode is the CBORNode wrapping of the `record` struct (go-threads/cbor/record.go)
    ```go
    // record defines the node structure of a record.
    type record struct {
        Block  cid.Cid
        Sig    []byte
        PubKey []byte
        Prev   cid.Cid `refmt:",omitempty"`
    }
    ```
    where `Block` should resolve to an EventNode (go-threads/cbor/event.go)
    ```go
    // event defines the node structure of an event.
    type event struct {
        Body   cid.Cid
        Header cid.Cid
    }
    ```
    where `Header` is 
    ```go
    // eventHeader defines the node structure of an event header.
    type eventHeader struct {
        Key []byte `refmt:",omitempty"`
    }
    ```
    
[^thread-def]: A `ThreadId` is a random identifier for raw (ie. not-ACL) threads. `LogId` identifies the log, derived from the IdentityKey (can be, but doesnt need to be the privkey of PeerId {assumption})

[^qn-rot-servicekey]: Is `PubKey` intended to rotate the service key, such that the history remains traversable? Is this implemented as such in go-threads? Does it make sense to rotate the read key in a similar way?

[^strong-synchronicity]: Here strong synchronicity is understood to be a system where the client requires timely updates to assert validity of the state (eg. no network partition); for a multi-writer-log with its head written to a BFT substrate the validity of the multi-writer-log is given by the validity of the substrate and the integrity checks on the log itself from the head down. [todo: well-defined?]

[^substrate-explainer]: a BFT substrate can be a suitable candidate from any of the following: Ethereum, metachains over Ethereum(testnet), cosmos zone, polkadot parachain, ava(testnet), or others

[^exploration-is-it-a-merkle-clock]: metachains / IBC / ... is a merkleclock
    http? make request: this is not a merkleclock, because we dont want wait for client's log update;
    BUT, we actually do, if we have a compound action `{mtx_to_update_SWL; record}`
    