A social contract is a voluntary agreement between people that is specified, undertaken, and fulfilled in the digital realm. It embodies the notion of “code-is-law”, in that a digital social contract is in fact a program – code in a social contracts programming language (defined recently [dsc]), which specifies the digital actions parties to the social contract may take; and the parties to the contract are entrusted, equally, with the task of ensuring that each party abides by the contract. Parties to a social contract are identified via their public keys, and the one and only type of action a party to a digital social contract may take is a “digital speech act” – signing an utterance with her private key and sending it to the other parties to the contract.
In a companion paper [dsc], we presented a formal definition of a digital social contract as agents that communicate asynchronously via digital speech acts, where the output of each agent is the input of all the other agents. In particular, an abstract design for a social contracts programming language is offered there and it is demonstrated, via programming examples, that key application areas, including social community; simple sharing-economy applications; egalitarian currency networks; and democratic community governance, can all be expressed elegantly and efficiently as digital social contracts. We refer to [dsc] for the definition and motivation for digital social contracts.
Our goal in this paper is to take the abstract notion of a digital social contracts [dsc] and describe a fault-tolerant distributed implementation of such digital social contracts. To do so, we proceed as follows:
We recall from [dsc] the definition of digital social contracts as an abstract transition systems, termed SC.
We recall standard notions of implementation among transition systems.
We define incrementally a sequence of transition systems, as detailed in Figure 1: First, a distributed implementation; then a strict fault-tolerant implementation, in which agents wait for actions to be finalized before basing actions on them; then, a relaxed implementation, in which, similarly to blockchain protocols, agents may act based on non-final acts, but might have to abandon these acts if they are discovered later to be based on a double-act; finally hash pointers are added.
The final result is a novel blockchain architecture that is distributed with a blockchain-per-person, partially-ordered, locally-replicated, asynchronous, peer-to-peer, with each agent being both an actor and a validator, environmentally-friendly, and egalitarian, as detailed in Table 1.
|Standard Blockchain||Digital Social Contracts|
|1. Central vs. Distributed||One blockchain for all||A blockchain per person|
|2. Totally- vs. Partially-Ordered||Linear global history||Partial ordering among personal histories|
|3. Global vs. Local||Actions replicated globally||Local replication among parties to a contract|
|4. Synchronous vs. Asynchronous||Actions synchronized globally by a single (rotating) miner||Each party synchronizes actions independently|
|5. Client-Server vs. Peer-to-Peer||Miners vs. validators vs. clients||All are equal as actors and validators (and minters)|
|6. Resource-Hogging vs. Frugal||Energy-hogging (Proof-of-Work) or capital-hogging (Proof-of-Stake)||Self-Sufficient|
|7. Plutocratic vs. Egalitarian||Proof-of-Work/ Proof-of-Stake||Egalitarian control|
While the aim of this paper is to formally define our fault-tolerant distributed implementation in a mathematical way, we hint on certain possibilities of practical implementation of a system implementing the mathematical models developed herein, and also relate such an implementation to the programming language developed for social contracts.
1.1 Related Work
A fundamental tenet of our design is that social agreements are made between people who know and trust each other, directly or indirectly via other people that they know and trust. This is in stark contrast to the design of cryptocurrencies and their associated smart contracts, which are made between anonymous and trustless accounts. A challenge that cryptocurrencies address is how to achieve consensus in the absence of trust, and their solution is based on proof-of-work [POW] or, more recently, proof-of-stake [POS] protocols. In contrast, social contracts are between known and trustworthy individuals, each expected to posses a genuine (unique and singular) identifier [ggid] (see therein discussion on how this can be ensured). Hence, a different approach can be taken. In our approach, the integrity of the record of actions taken by the parties to the social agreement is reached between parties to the agreement, not between external anonymous “miners”, as in cryptocurrencies. This gives rise to a much simpler approach to fault tolerance.
In particular, our approach does not suffer from forks/delayed finality as for example the Bitcoin protocol [bitcoin], and does not need to reach Byzantine Agreement [BA]. Instead, agents ratify actions of each other, an action is decided to be final when it is known that a supermajority of the agents ratify it, and agents take an action that depends on actions of others only once they are decided to be final. As a result, the handling of “double spend”, a key challenge for cryptocurrencies, is much simpler.
Hence, rather than building on an existing blockchain architecture, we propose here a new one. Digital social contracts are (also) an abstract model of computation, and as such could be implemented on any Turing-complete computational model, in particular on a single centralized computer, on a client-server system, as a software-as-a-service application, as a smart contract on a public (permissionless) blockchain, or on a permissioned blockchain. Digital social contracts aim to support digital communities that are both sovereign and egalitarian: sovereign over their membership and conduct, and egalitarian in exercising their sovereignty. Open peer-to-peer systems, e.g., Scuttlebut [tarr2019secure], do not exercise sovereignty over membership; federated systems, e.g.. Mastodon [raman2019challenges], do not exercise egalitarian governance, in that each server operator has full control over the community residing on its server. Equality without sovereignty is easily achieved, in principle, among the clients in a client-server architecture. But democratic governance of a system is impossible if the members are not the sovereign, as any decision they make can ultimately be overruled by the sovereign, who can simply unplug/erase/block the community. Blockchain is the first technology to offer sovereignty to its participants: Nobody can unplug Bitcoin or Ethereum, for example; both will keep running as long as someone somewhere keeps running their protocols. However, present public (permissionless) blockchains are not a feasible vehicle for smart contracts, for several reasons. First, their Proof-of-Work protocol is environmentally harmful, and hence cannot be supported by any person of conscience, let alone an effort aiming at a just society. Second, they, as well as novel environmentally-friendly consensus protocols [POS, gilad2017algorand], are plutocratic, providing more power and more wealth to those who are already wealthy; hence they are neither egalitarian nor just. Standard private (permissioned) dedicated blockchains can address the challenge of sovereignty and, possibly with major extra effort, could be made egalitarian and just. However, the standard blockchain architecture has one global blockchain shared by all agents, which stores all actions by all agents in a single linear data structure; the entire blockchain is fully-replicated to all agents, and all actions of all agents are synchronized by a single (rotating) agent. These aspects hamper the scalability of the standard blockchain architecture. Here we present a fault-tolerant distributed transition system to realize digital social contracts. The transition system is such in which each agent stores its sequentially-indexed actions, as well as a partial order wrt. the sequentially-indexed actions of other agents, that are parties to some contract.
We assume a given finite set of agents and a finite set of actions . Each agent is associated with a genuine (unique and singular) [ggid] identifier, which is also a public key of a key-pair.111We identify the set of agents with the set of parties to the agreement. Extensions will allow an agent to be a party to multiple agreements, and different agreements to have different sets of agents as parties. Actions are identified with their string representation. We expect agents to be realized by computer programs operating on personal devices (e.g. smartphones) of people. Hence, we refer to agents as “it” rather than as he or she.
We identify an agent with its genuine public identifier, and denote by the result of agent signing the action with the private key corresponding to . We assume computational hardness of the public-key system, namely that signatures of an agent with a given identifier cannot be produced without possessing the private key corresponding to this identifier. To avoid notational clutter we do not distinguish between finite mathematical entities and their string representation. Identifying agents with their genuine identifiers makes totally ordered (by the numeric value of the identifier, namely the public key) and hence allows defining tuples and Cartesian products indexed by . If is a tuple indexed by , then we use to refer to the element of . We say that except for to mean that the tuple is obtained from by replacing its element by . In particular, if is a sequence, then we say that , except for , to mean that is obtained from by appending to the sequence . We denote by the empty sequence, and overload set notation viewing a sequence also as a set of its elements, in case the elements are distinct (which is always the case here). Given a sequence , a sequence is a prefix of , , if , for some .
We employ a standard notion of a transition system:
Definition 1 (Transition System).
Given a set , referred to as states, transitions over is a set . A transition system consists of a set of states , an initial state , and a set of transitions over , with written as . A run of is a sequence of transitions from the initial state. A family of transition systems over is a set of transition systems of the form where is a set of transitions over .
A family of transition systems is best thought of as the abstract / semantic / syntax-free counterpart of a programming language, where each transition system is the abstract counterpart of a program in the language.
Definition 2 (Implementation).
Assume two transition systems and , and a function , where , referred to as a semantic mapping. Then implements via if:
For every transition , there is a sequence of transitions , , such that and .
For every transition , either or .
can implement if there is a semantic mapping via which implements .∎
Definition 3 (Morphism, Strict).
Given two transition systems and , a semantic function , where is a morphism if implies ; and strict if implies .
That is, in a strict morphism the implementing process provides all the transitions of the implemented process [hesselink1988deadlock].
A strict morphism is an implementation in which every transition of the implementing transition system is mapped to exactly one transition of the implemented transition system, and vice versa. Hence:
A strict morphism among two transition systems is an implementation.
Definition 4 (Compiler).
Given two families of transition systems, , , consider a pair of functions , where is a semantic mapping and is referred to as a compiler. Then implement if for each , implements via . We say that can implement if there is a pair of functions as above that implement .
Eventually, we aim to use the framework developed here to indeed prove that the Social-Contracts Programming Language we are designing implements the abstract transition system of social contracts described herein.
Given two transition systems and , let be a bijection , where , and for all iff . Then both and are implementations.
Observation 3 (Transitivity and Compositionality of Implementations).
Let , and be families of transition systems and and as above. If can implement and can implement , then can implement . If implements by and implements by , then implements by .
3 SC: An Abstract Model of Digital Social Contracts
Here we recall the formal model of digital social contracts [dsc].
Remark 1 (Parties, Roles, and Parameterized Social Contracts).
Agents should be able to participate simultaneously in multiple social contracts. Furthermore, a contract may have multiple parties with the exact same role. To address this properly, we should describe digital social contracts as a set of roles, each specified by a parameterized procedure, and bind the formal parameters to actual agent identifiers upon execution of the contract. This is akin to the standard legal practice of using a textual contract template, with role names as parameters (e.g. Landlord, Tenant), and filling in the identities of the parties assuming these roles in an instance of this contract template upon its signature. We defer this distinction between formal and actual parameters in a social contract to avoid notational clutter, and name the parties to the social contract by their genuine identifiers, i.e., their public keys. Later we describe a design for a practical Social-Contracts Programming Language, which will naturally make this distinction.
A digital social contract consists of a set of agents, identified via public keys, and connected via a reliable, asynchronous, order-preserving communication network. Namely, we assume that between any two agents in the network, the network delivers all messages sent from one agent to another – correctly, eventually, and in the order sent.222As agents have public keys with which they can sign their sequentially-indexed messages, such a network can be easily realized on an asynchronous network that is not order-preserving and is only intermittently reliable. All that agents can do within a digital social contract is perform digital speech acts (henceforth, acts), which are sequentially-indexed utterances, signed by the agent and sent as messages to all other agents that are parties to the contract, as well as receive such messages. Example acts are “I hereby transfer three blue coins to Sue” and “I hereby confirm the room reservation by Joe”. A digital social contract specifies the digital speech acts each party may take at any state. For example, a social contract regarding the blue currency may specify that I can say that I transfer three blue coins to Sue only in a state in which I in fact have at least three blue coins; and I can say that I confirm Joe’s room reservation only if I have not already confirmed a conflicting reservation.
Our abstract notion of a digital social contract identifies a digital social contract with a transition system. The state of a digital social contract, referred to as a ledger, is composed of the states of each of the agents participating in the contract, referred to as their history, which is but a sequence of digital speech acts. The history of an agent consist of digital speech acts it experienced, in particular: acts by , referred to as -acts, in the order taken, interleaved with acts by the other agents, in the order received from the network. Hence, at any ledger that is a state of the computation, the -acts in the history of agent must be a prefix of the -acts in the history of , for any and . We call such a ledger sound. Next we formalizes this informal description.
We assume a given set of actions . Signing an action by an agent makes the action non-repudiated by . All that an agent that is party to a digital social contract does, then, is perform digital speech acts, as well as receive such acts performed by others, resulting in a sequence of non-repudiated acts - a history of crypto speech acts.
Definition 5 (-act, History).
We refer to , the result of signing an action by agent , as a -act, let denote the set of all -acts by all , and refer to members of as acts. A history is a finite sequence of acts , , , , , . The set of all histories is denoted by .
Next, we define a pair histories to be consistent if they agree on the subsequences signed by each agent.
Definition 6 (Prefix, Consistent Histories).
Given a sequence , a sequence is a prefix of , , if , for some . We apply the notation , of restricting a history to the subsequence of -acts.
Two agent histories are consistent if either or vice versa for every .
A ledger of a digital social contract is an indexed tuple of histories of the parties to the contract. Ledgers are the states of the social contract transition system.
Definition 7 (Ledger).
A ledger is a tuple of histories indexed by the agents , where is referred to as the history of agent in , or as ’s -history.
Following Definition 6, we apply the notation to denote the subsequence of -acts in the -history in .
Our key assumption is that in a ledger that is a state of a computation, each agent’s history is up-to-date about its own acts. Therefore, for agent histories to be consistent with each other, the history of each agent can include at most a prefix (empty, partial or complete) of every other agent’s acts. In particular , the history of cannot include -acts different from the one’s taken by ; nor can it run ahead of and “guess” acts might take in the future.
Note that a ledger is not a linear data structure, like a blockchain, but a tuple of independent agent histories, each of them being a linear sequence of acts. Furthermore, note that , the history of in ledger , contains, of course, all -acts, but it also contains acts by other agents received by via the communication network. Also, note that the -history may be behind on the acts of other agents but is up-to-date, or even can be thought of as the authoritative source in , regarding its own -acts.
Definition 8 (Ledger Diagonal, Sound Ledger).
Given a ledger , the diagonal of , , is defined by for all . A ledger is sound if for every .
As we assume that each agent is up-to-date about its own acts, the diagonal contains the complete sequence of -acts for each agent . Thus, each agent history in a ledger reflects the agent’s “subjective view” of what actions were taken, where the diagonal of a ledger contains the “objective truth” about all agents, as the following observation shows.
If a ledger is sound, then every pair of agent histories in is consistent.
We have defined the states of the transition system, and are now ready to define the transitions themselves.
Definition 9 (Transitions).
The set of social contract transitions consists of all pairs where except for , for some and . The transition is referred to as a -transition, and can also be written as .∎
Definition 10 (Input, Output and Sound Transitions).
A -transition is output if and input if . A transition is sound if it is either input with or output.
If is sound and is sound then is sound.
An Output -transition does not violate soundness as by definition. An Input -transition does not violate soundness thanks to the requirement that . ∎
The next definition aims to capture formally the following two informal requirements:
Output: That an agent may take a -act in state based solely on its own history . In particular, is free to ignore, or to not know, the other agents’ histories in .
Input: That must accept messages from the communication network in any proper order the network chooses to deliver them. In particular, in any state , can accept from any other agent the next consecutive -act not yet in ’s history.
Definition 11 (Closed Set of Transitions).
A set of transitions is:
Output-closed if for any -act , , , and any two output transitions , , if then iff . Namely, if every output -transition is a function of , independently of for all .
Input-closed if contains every sound input transition in .
Closed if it is output-closed and input-closed.
Definition 12 (Digital Social Contract).
A digital social contract among a set of agents is a transition system with ledgers as states , initial state , and a closed set of transitions . The family of all digital social contracts over is denoted by , and is abbreviated as .
We refer to as the family of abstract social contracts, in contrast to its more concrete implementations discussed next. In particular, we view abstract social contracts as specifications for programs in the Social-Contracts Programming Language, as discussed in [dsc].
Remark 2 (Liveness Assumption).
We make a general weak liveness assumption for this and all transition systems described here, that no transition is enabled at every suffix of an infinite computation without eventually being taken. In other words, a continuously enabled transition is not starved indefinitely.
This completes the definition of the abstract computational model of digital social contracts. Further liveness and fairness requirements for digital social contracts will be discussed in subsequent work.
Note that in the present asynchronous model, neither agent histories nor ledgers have a built-in notion of time. We would like, however, social contracts to be able to have a notion of time and refer to it. Adding time to digital social contracts is an anticipated future extension.
4 DSC: A Distributed Implementation
As a step towards a fault-tolerant distributed transition system, we first define a distributed transition system and prove that it is an implementation of digital social contracts. In particular, we introduce a notion of a message store into the model, to acknowledge that agents cannot see the histories of other agents, but rather communicate to each other their digital speech acts. The message store models point-to-point messages in transit – sent by one agent and not yet received by the other. Informally speaking, instead of having a notion of soundness that implies that each agent effectively knows the diagonal of the ledger, the system is distributed so that each party to the agreement learns of the diagonal incrementally and independently, through message passing.
Transitions are as in the abstract social contracts, but their context changes: the system contains a communication network via which the agents interact, so an Input -transition indeed inputs a message addressed to from the network, and an Output -transition outputs messages to the network for all . Indeed, we model a reliable asynchronous communication network among the agents via an addressed message store:
Definition 13 (Addressed Message Store).
A set is referred to as an addressed message store, where is any set of mathematical objects (we do not wish to limit the type of messages sent). A -act is sent to through by adding to , and is received by removing it from . Note that the message store stores to say that some sent the message to .
Recall that the agent signs the message , so, even though we store objects of the form , where is the receiver and is the message, the original sender is implicitly there as well, as signs . For this DSC distributed model we assume that message from agent to agent are delivered in the order sent, for any . This can be achieved by the sender indexing messages and by the receiver buffering out-of-order messages. To avoid notational clutter, we do not show this indexing explicitly in DSC; this will be done subsequently in the fault-tolerant implementation, where indexing faults have to be dealt with.
The network is the new component in a distributed social contract state, that is, not only we have a ledger in each state, but also a message store:
Definition 14 (Distributed Ledger, Consistent).
A distributed ledger is a pair , where is a ledger and is an addressed message store. Then is consistent if is sound, and for a -act iff .
Namely, consistency in a distributed ledger not only refers to the pairwise consistency of the agent histories in , but also requires that the addressed message store records precisely the entire “communication gap” from to , namely include output -acts destined to and not yet input by , recorded as the difference between and , for every . Note that, in a consistent distributed ledger , it holds that is uniquely determined by .
Observation 6 (Ledger determines Message Store).
If are consistent, then .
Assume that this is not the case, and, wlog., consider a message in . If then both states are inconsistent. Else assume . If then is inconsistent. If not then is inconsistent. Either way, at least one of the states is inconsistent. ∎
We are now ready to define the distributed transition system. It is similar to the abstract transition system of digital social contracts, except that it employs a communication network and the extended notion of consistency that comes with it.
Definition 15 (Distributed Transitions).
The set of distributed social contract transitions consists of all pairs where is consistent, except for some , some , and some , and either:
Input: , and (that is, inputs from the message store some message coming from some other agent and addressed for , appends this message to its own history);
Output: and and (that is, performs an action, appends it to its own history, and outputs the message, for each other agent separately, to the message store).
The distributed transition is referred to as a -transition, and can also be written as .∎
Lemma 1 (Preservation of Consistency).
Let be a distributed ledger transition. If is consistent then so is .
If , then this is an input transition by . Thus, except for . Notice that , and , thus, in particular for a -act iff (the second requirement for distributed consistency). Furthermore, is sound as must be in the history of .
If , then this is an output transition by . Thus, differs from in containing for all , hence, if is consistent then so is . ∎
We are interested in the computational model of distributed social contracts as far as it implements abstract social contracts. Hence we define for every social contract transition system SC its distributed counterpart D(SC), and then prove that D(SC) implements SC.
Definition 16 (Corresponding Distributed Transition System).
Given an abstract transition system , its corresponding distributed transition system has states :
and transitions :
The function is a strict morphism.
According to Observation 6, the ledger uniquely determines the message store. Hence an SC transition uniquely determines a D(SC) transition and vice versa. ∎
Since a strict morphism is an implementation, we have the following:
implements for every .
4.1 The Distributed Nature of DSC
Note that DSC is quite similar to SC, with the main difference that we have the explicit addressed message store in DSC, modeling the communication. Importantly, however, note that the transitions of DSC can be realized from an agent point of view; that is, it is possible to view each transition of DSC as a transition decided upon by a specific agent. This is so as each agent can output a message at its own will; and, crucially, each agent can look at the message store and, if it finds a message addressed to it, input it to its own ledger. We remark that this cannot happen in SC, as agents cannot easily look inside other agents’ ledgers. Indeed, the main reason we consider DSC is to model the agent-based communication and point of view of the system.
5 FTDSC: A Fault Tolerant Implementation
In the section above we described distributed transition systems, and showed that D(SC) implements SC.
Before we describe our implementation, we discuss what are faulty agents and what kind of fault tolerance we aim to achieve.
5.1 Faulty Agents, Fault Tolerance, and Double Acts
We are interested in a distributed implementation that can withstand faulty agents, which is amenable to formal analysis.
In particular, we are interested in double acts. Double spend is the most notorious fault against which cryptocurrency protocols aim to withstand [chohan2017double]. In it, an agent communicates to some other agents one transaction, and to others another transaction; each legal on its own. But, they cannot both be taken, in either order. For example, two large payments taken from the same account, which has a balance insufficient to cover both.
A double spend is a special case of a double act, where two output -transitions can be taken, and , , and instead of taking one of them and communicating it to all, communicates to some agents that it has taken and to others that it has taken , by , , , but and . Here we aim to address double acts; in particular, we consider faulty agents that might perform double acts, and may behave arbitrarily regarding ratify messages: fail to send them or send incorrect ones. We show our fault-tolerant distributed transition system can withstand and faulty agents, if there are not too many of them.
To achieve fault tolerance, here we first follow the Byzantine-resilient broadcast protocol of Bracha (1987) [bracha1987asynchronous], with some modifications. Later we relax the requirement that agents need to wait for actions to be finalized, and then add hash pointers. But we begin with a modification of Bracha [bracha1985asynchronous].
While the protocol of Bracha uses two rounds of messages – an echo message, followed by a ready message – when using our transition system a single message type is enough for a fault-tolerant broadcast. Unlike Bracha’s protocol, that assumes unsigned messages, our acts are signed by the actor. Hence, we can use a single message type, ratify, which agents both send and echo (forward).
Definition 17 (Ratification acts).
A ratification act of an agent has the form , where is an act and is a reserved action. Denote the set of all ratification acts by .
Informally, such a ratification act conveys the digital speech act “I, agent , hereby ratify the message ”. The general idea is that an agent would ratify a message if it is aware of it and can verify its validity (this means also that an agent would not later ratify a contradicting message that forms a double act with ). An agent would then receive an input message only after it is aware of a supermajority of ratifications for (including both its own ratification, if indeed it has ratified ). However, a faulty agent may deliberately send incorrect ratifications, or correct ratifications to only some of the agents. Thus, our simple solution is that an agent that receives a new ratification, it forwards it to all other agents. This results in the message complexity of this protocol being , higher than that of Bracha’s . A simple remedy would be to not forward ratifications, but for agents that see that another agent knows ahead of them that an act is final (by the agent acting based on it) to request the missing ratifications from that agent. This would bring the expected message complexity down to . Here we present the simple protocol without this improvement.
The basic idea of our fault-tolerant transition system is that an act is considered final if sufficiently many agents ratify it. What is “sufficiently many” depends on how many faulty agents are there.333 Indeed, this number might not be known, but it may be estimated, or at least bounded.
Indeed, this number might not be known, but it may be estimated, or at least bounded.As the key challenge is double acts, and we assume that non-faulty agents do not ratify two conflicting acts, we must require sufficiently many ratification so that, under this assumption, no two conflicting acts will ever get finalized.
Hence, we assume some bound on the fraction of faulty parties to the contract. We then employ a -supermajority, , with which non-faulty agents may conclude whether a -act is final despite or other agents being faulty.
Definition 18 (-supermajority).
Given , a set of agents is a -supermajority if .
A message is finalized if a supermajority ratifies it:
Definition 19 (Finality).
Assume , a set of ratifications , and a -act for some . Let and let . Then finalizes if .
Note that if finalizes then so does . The next observation is crucial, as it means that, if indeed we wait for a message to be finalized, then we can safely input it, as, using this observation, a conflicting double-act will never be finalized.
Assume , two -acts and and a set of ratification. If no more than agents ratify both and , then at most one of and is finalized by .
By a counting argument. ∎
5.3 A Basic Fault-Tolerant Implementation
The fault tolerant implementation assumes a bound on the fraction of faulty agents among all agents, and chooses some . The key idea of the fault-tolerant implementation is that:
All agents ratify all acts of all agents.
But, an act of an agent can be ratified only after all previous acts in the agent’s history are final, and the act is enabled (according to the underlying digital social contract) by this final history of the agent.
An act is final if ratified by a -supermajority of the agents.
All terms are defined below. The implementation described in this section is naive; in particular, the following two aspects of it can be improved:
Message-complexity, at the cost of complicating the data structures and using additional message types.
Throughput, by agents performing acts based on yet-non-final acts by other agents, at the risk of having to revert an action in case it is based on an act discovered to be part of a double act before being finalized.
These improvements are discussed in the next section.
First, we define fault-tolerant acts. They are different from ordinary acts in two respects: They are indexed, and they have preceding acts they are based on.
Definition 20 (Fault-Tolerant Act).
A fault-tolerant act has the form , where , and is a finite sequence of preceding input acts by . We define fault-tolerant histories to be the set of all of sequences of fault-tolerant acts over and and the fault-tolerant ledgers to be all -indexed fault-tolerant histories.
The intention is for to include all input acts by since ’s previous output act, so that other agents can validate the -act ; and for to sequentially-index its acts, being the current index, so that other agents can identify double acts by . Next we aim to formalize this intention.
Definition 21 (Simple History and Ledger).
Let be a fault-tolerant ledger, where
Then ’s simple view of ’s history is , and the simple ledger corresponding to is defined by for all . The ledger is sound if
Note that is just ’s history according to , and that , namely ’s acts in v’s simple history (and which all preceding inputs are ignored in ’ history) are the same as ’s acts in ’s view of ’s simple history (in which all preceding input are ignored in ’s view of ’s history). Hence the following:
Let be a fault-tolerant ledger, if is sound then is sound.
If then . Since , this implies that , or that , implying that is sound. ∎
We define a fault-tolerant distributed ledger for this setting. As in SC an action of an agent depends on its history, for agent to ratify the action of agent , needs to know ’s history. Hence we employ fault-tolerant acts. In addition, a configuration contains a bag of meta messages for each agent, which contains all meta messages sent or received by the agent. Here, the bag contains only ratify messages, but later it will contain other meta messages. The configuration also contains an addressed message store, as in DSC, but augmented to communicate also meta messages.
Definition 22 (Fault-Tolerant Configuration, Consistent, -Finality).
A fault-tolerant configuration is a triple , where is a fault-tolerant ledger, is a -indexed tuple of sets of meta messages, and is an addressed message store. It is consistent if is sound and if are consistent.
Now we are ready to define the transitions of FTDSC. As we are interested in a fault-tolerant distributed implementation of social contracts, we will consider a given abstract transition system SC and derive from it the fault-tolerant transition system FTD(SC). We will then prove that it implements this underlying SC, and that it does so even in the presence of a bounded number of faulty agents.
We consider first the “object-level” transitions of input and output actions; these are derived from DSC transitions, however, to achieve fault tolerance – in particular to allow other agents to verify whether some act of another agent is legit, according to the underlying digital social contract – an output act contains also the input acts that preceded it, , as these will allow for such a verification. Furthermore, an input -transition may be taken only for a message that is -final. We then consider the “meta-level” input and output Ratify transitions.
Definition 23 (Object-Level Fault-Tolerant Transitions: Input and Output).
Let and be a set of abstract social contract transitions. Then the corresponding set of object-level fault-tolerant distributed transitions consists of all pairs where is consistent, , except for some , some , and some , , and acts , provided and either:
Input: , , is finalized by , and .
Output: and where , where is a maximal suffix of input -acts in (i.e., containing all inputs, starting from the last output).
The transition is referred to as a -transition and can also be written as .∎
Note that the key difference from DSC to FTDSC is that an agent can only input a -act if knows that is final, namely that there is a supermajority of ratifications for in ’s set of meta messages ; and that, to allow this, there is a new kind of meta-action, namely a ratify action, which is stored in and not in as there is no reason to linearize these meta-messages within histories or among themselves. In output acts, includes all input acts since its most recent output act.
For one agent to ratify agent’s act, agent needs to know agent ’s history. Fortunately, each ’s history contains not only a prefix of ’s acts, in , but it also contains all of ’s input acts, provided piecemeal in the parameter in every -act. One agent ratifies an act of another agent if two conditions hold: the input acts that precede it are final, and the act is a valid transition, relative to some specification. As we are interested in implementing social contracts, we use the social contract to be implemented as the specification of valid transitions.
Anticipating our next, relaxed fault-tolerant transition system, we introduce in the following definitions a regret-free function rf on ledgers. For now, consider it to be the identity function. It will gain additional meaning subsequently, when we relax a bit.
Definition 24 (Meta-Level Fault-Tolerant Transitions: Ratify).
Given a set of abstract social contract transitions , the corresponding set of meta-level fault-tolerant ratify transitions consists of all pairs , , where:
Input Ratify: , , if then , except for ; otherwise, i.e., if , then and .
Output Ratify: , , every is finalized by , for some , , , where and have the same agent and same index in the ratified action, except for , and .
The transition is referred to as a -transition, and can also be written as .∎
Namely, an Input Ratify -transition receives a ratification message from the communication network , and, if it is new, then it adds it to the meta-bag and echoes it to all agents. An Output Ratify -transition sends a message to all other agents via , provided has not ratified before, and provided that the -act is enabled by ’s view of ’s history according to the specification SC, and provided that all the inputs that preceded it are final. The check regarding and verifies that does not ratify the same action twice and, furthermore, that does not ratify double acts.
Definition 25 (Fault-Tolerant Distributed Implementation).
Given a social contract , its corresponding fault-tolerant distributed transition system with fault-tolerant distributed ledgers as states , initial state , and transitions .
Next we show that FTD(SC) implements SC.
Proposition 1 ( implements ).
Given a social contract , then implements .
We define a mapping from states to states as follows: Namely, takes a fault-tolerant distributed configuration, extracts from it the fault-tolerant ledger and simplifies it into a simple ledger. The implications of this mapping are that object-level fault-tolerant transitions are mapped to their corresponding abstract transitions, input and output, respectively. Meta-level ratify transitions are mapped to stutter. Observe now that every run is mapped into an run as the fault-tolerant object-level transitions are defined according to their corresponding abstract transitions.
To show the other direction, we map an SC run into an FTD(SC) run as follows. Every SC output transition is mapped into its corresponding FTD(SC) output transition, followed by performing the finite number of subsequent output ratify and input ratify transitions to completion, thus finalizing the actions in the eyes of all other agents. An SC input transition is mapped into its corresponding FTD(SC) input transition, which can be taken as all the actions in its preceding inputs have been finalized. A formal proof would show that FTD(SC) implements D(SC) and, using Corollary 1 and Observation 3, conclude that FTD(S) implements SC. ∎
So, above we showed that indeed corresponds to ; in a way, it means that both are equivalent whenever there are no faulty agents. As the reason for the definition of is to be fault tolerant, next we show that indeed it achieves our desired fault tolerance properties.
Proposition 2 (Safety, Liveness, Soundness of FTD(SC)).
Let for some . If a fraction of at most of the agents are faulty then:
Safety: No incorrect act will be finalized; that is, there is no reachable state in which an act that is not correct according to the corresponding specification is finalized.
Liveness: If , then every correct act will be finalized; that is, in any run on a transition, any act that is correct wrt. the underlying will be eventually finalized.
Soundness: For a double act, not both acts will be finalized; that is, there is no reachable state in which both acts of a double act are finalized.
We sketch the proof of each of the claims above.
For safety, all non-faulty agents will not ratify any incorrect transition, hence it cannot accumulate a -supermajority of ratifications and hence will not be finalized by any non-faulty agent.
For liveness, all non-faulty agents will eventually ratify every correct action by the Liveness Assumption (Remark 2), and, if , then it can achieve a -supermajority of ratifications.
For soundness, no non-faulty agent will ratify two double acts, hence not both can reach a -supermajority of ratifications. ∎
6 RFTDSC: Relaxed Recovery from Double Acts
Above, in our Bracha-like transition system, we required that agents do not input non-final acts. While simple, we relax this requirement to improve the throughput of our system; in particular, we consider the possibility of agents not waiting until supermajority to input messages. That is, the general idea is that an agent may take as input a non-final message from , as long as agent is not aware that is part of a double act. The crucial point is that, it is possible that, still, is part of a double act; thus, we have the following:
As soon as an agent identifies a double -act by another agent , it requests all agents to faultlist , while providing non-repudiable evidence for the double -act: two conflicting acts with the same index signed by . Such a non-repudiable evidence is needed so that faulty agents could not cause non-faulty agents to be faultlisted. Then, every agent that receives the faultlist message can confirm that indeed has performed a double -act, and then faultlist . Once an agent faultlists , it stops ratifying -acts.
Now, regarding the -acts from the double act onwards, all agents broadcast reject for all such acts, except for acts that they have already ratified.
If a -superminority (i.e., at least of the agents) reject , then will never reach a -supermajority of ratifications, and hence an agent that has taken this act as input regrets this act and all subsequent acts taken subsequent to that act and prior to regretting it – note that regretting may have consequences (that is, if an agent acted upon the belief, based on some other agent’s act that was not final, then might need to bear the consequences).
The result is that a double-acting agent is faultlisted, at most one of its double acts is finalized, and soon after being faultlisted, all further -acts are ignored by all. Still, there is some damage that could be done to non-faulty agents that acted based on yet-non-final -acts. Indeed, a cautious agent might still want to wait for finalization of another agents’ act, especially if it has major consequences (e.g., a large payment for an expensive product). However, we expect that as trust increases, more and more agents will be willing to take the risk and often not wait for finalization, therefore increasing the throughput of the system.
So, similarly to , states of the transition system we consider here, named , are triples , but this time the bag of meta-messages contains, in addition to ratify messages, also faultlist and reject messages. Note that, unlike faultlist and reject, we view a regret(m) -act as an object-level -act, as it undoes all input and output -acts taken since and including , and therefore it is indexed and stored in ’s history like other object-level acts. More precisely, the new acts are:
, by which an agent reports a double -act; where , , and . This message is broadcasted to and echoed by all, and recorded by the receiving agent in .
, in which an agent declares that it did not ratify the message , and will never do so. The act is broadcasted to all and recorded by the receiving agent in .
, by which an agent regrets all acts indexed and above, not including this regret. This is an object-level act in that it is indexed and recorded in in the history of the actor and each recipient.
The basic intuition of this implementation relates to the connection between supermajority and superminority, so the main idea, of using superminority for deciding upon the fate of a recently-found double act, is explained below.
Definition 26 (-superminority).
Given , a set of agents is a -superminority if .
Observation 10 (Superminority vs. Supermajority).
Assume and that all agents vote to either reject or ratify an act. Then, if a -superminority votes to reject the act, then there is no -supermajority that ratifies the act. Furthermore, the result still holds if all votes are signed and some (faulty) voters vote both reject and ratify, provided that such votes are counted as reject.
By a counting argument. ∎
Hence, if a superminority rejects an act, even in the presence of faulty agents, then this ensures that the act will never be finalized, and hence can/should be abandoned.
We are ready to define our transition system RFTD(SC). Formally, it is similar to FTD(SC), but here we use not only for ratify actions, but also for faultlist, reject, and regret actions, and, correspondingly, we have a richer set of transition types.
Next we define the faultlist and reject transitions.
Definition 27 (Relaxed Meta-Level Transitions: faultlist and Reject).
Given the set includes all transitions for all , where one of the following holds:
Output Faultlist: , are a double -act for some , , and , except for ; i.e., agent broadcasts (via ) a faultlist message, shaming another agent for doing a double act with the pair , and record this faultlist in its meta-messages bag.
Input Faultlist: , , , are a double , except for ; i.e., agent sees a faultlist message addressed to it in the message store, in which an agent is shaming another agent for doing a double act , so takes the message out from the message store, broadcasts to all other agents, and records the message in its meta-messages bag.
Output Reject: , is a -act, is faultlisted in , , , , , except for ; i.e., is already faultlisted in , did not yet ratified some -act , so rejects the -act .
Input Reject: , , except for , and ; i.e., sees that rejects some message (of some other agent), takes it out from the message store and records it.
Now, regret transitions.
Definition 28 (Relaxed Object-Level Transitions: Regret).
Given , the set of object-level relaxed fault-tolerant transitions consists of all pairs where is consistent, , except , for some , , and either:
Output Regret: , prevents finalizing , .
Input Regret: , , .
One additional change is needed. Recall that an output fault-tolerant -transition corresponding to an abstract social contract employs a simplifying function on its ledger to determine whether a transition is enabled. So here, the simplifying function has to be updated to accommodate regrets. Informally speaking, regrets causes to forget parts of the history; here is the formal revised definition.
Definition 29 (Regret-Free History and Ledger).
Let be a ledger. Define to be and define as follows:
If and for some , let