On implementing SWMR registers from SWSR registers in systems with Byzantine failures

The implementation of registers from (potentially) weaker registers is a classical problem in the theory of distributed computing. Since Lamport's pioneering work [13], this problem has been extensively studied in the context of asynchronous processes with crash failures. In this paper, we investigate this problem in the context of Byzantine process failures, with and without process signatures. We first prove that, without signatures, there is no wait-free linearizable implementation of a 1-writer n-reader register from atomic 1-writer 1-reader registers. In fact, we show a stronger result, namely, even under the assumption that the writer can only crash and at most one reader can be malicious, there is no linearizable implementation of a 1-writer n-reader register from atomic 1-writer (n-1)-reader registers that ensures that every correct process eventually completes its operations. In light of this impossibility result, we give two implementations of a 1-writer n-reader register from atomic 1-writer 1-reader registers that work under different assumptions. The first implementation is linearizable (under any combination of process failures), but it guarantees that every correct process eventually completes its operations only under the assumption that the writer is correct or no reader is malicious -- thus matching the impossibility result. The second implementation assumes process signatures; it is bounded wait-free and linearizable under any combination of process failures. Finally, we show that without process signatures, even if we assume that the writer is correct and at most one of the readers can be malicious, it is impossible to guarantee that every correct reader completes each read operation in a bounded number of steps.


Introduction
We consider the basic problem of implementing a single-writer multi-reader register from atomic single-writer single-reader registers in a system where processes are subject to Byzantine failures. In particular, (1) we give an implementation that works under some failure assumptions, and (2) we prove a matching impossibility result for the case when these assumptions do not hold. We also consider systems where processes can use unforgeable signatures, and give an implementation that works for any number of faulty processes. We now describe our motivation and results in detail.
In particular, it is well-known that in systems where processes are subject to crash failures, it is possible to implement a wait-free linearizable m-writer n-reader register (henceforth denoted [m, n]-register) from atomic 1-writer 1-reader registers (denoted [1,1]-registers).
In this paper, we consider the problem of implementing multi-reader registers from singlereader registers in systems where processes are subject to Byzantine failures. In particular, we consider the following basic questions: Is there a wait-free linearizable implementation of a [1, n]-register from atomic [1,1]-registers in systems with Byzantine processes? If so, under which assumption(s) such an implementation exist?
The above questions are also motivated by the growing interest in shared-memory or hybrid systems where processes are subject to Byzantine failures. For example, Cohen and Keidar [6] give f -resilient implementations of several objects (namely, reliable broadcast, atomic snapshot, and asset transfer objects) using atomic [1, n]-registers in systems with Byzantine failures where at most f < n/2 processes are faulty. As another example, Aguilera et al. use atomic [1, n]-registers to solve some agreement problems in hybrid systems with Byzantine process failures [1]. Moreover, Mostéfaoui et al. [15] prove that, in message-passing systems with Byzantine process failures, there is a f -resilient linearizable implementation of a [1, n]-register if and only if at most f < n/3 processes are faulty.

Description of the results
To simplify the exposition of our results, we first state them in terms of two process groups: correct processes that do not fail and faulty ones. We show that in a system with Byzantine failures the following impossibility and possibility results hold. For all n ≥ 3: The case n = 2 is special: we give a wait-free linearizable implementation of a [1,2]-register from atomic [1,1]-registers that works even if the writer and readers can be faulty. This simple version of the results, however, leaves several questions open. Intuitively, this is because the above results do not distinguish between the different types of faulty processes (recall that, by definition, Byzantine failures encompass all the possible failure behaviours, from simple crash to "malicious" behaviour). For example we may ask: what happens if we can assume that some processes (say the writer) are subject to crash failures only, while some other processes (say the readers) can fail in "malicious" ways? Is a wait-free linearizable implementation of a [1, n]-register from atomic [1,1]-registers now possible?
Note also that the above results consider linearizability and wait-freedom (intuitively, "safety" and "liveness") as an indivisible requirement of a register implementation. But it can be useful to consider each requirement separately. For example, what happens if we want to implement a [1, n]-register with the following properties: (1) it is always safe (i.e., linearizable) and (2) it may lose its liveness (i.e., it may lose its wait-freedom by "blocking" some read or write operations) only if some specific "pattern/types" of failures occur?
To answer such questions, we now consider linearizability and wait-freedom separately, and we partition processes into three separate groups: (1) those that do not fail, called correct processes, (2) those that fail only by crashing, and (3) those that fail in any other way, called malicious processes. In systems with a mix of such processes, we prove the following: (1) For all n ≥ 3, there is no wait-free linearizable implementation I n of a [1, n]-register from atomic [1, n − 1]-registers, even if we assume that the writer can only crash and at most one of the readers can be malicious.
In fact, we show that this impossibility result holds even if all the processes except the writer are given atomic [1, n]-registers that all processes can read; so the writer is the only process that does not have an atomic [1, n]-register.
(2) For all n ≥ 3, there is an implementation I n of a [1, n]-register from atomic [1,1]-registers such that: I n is linearizable, and I n is wait-free if the writer is correct or no reader is malicious. 1 Note that this implementation guarantees linearizability, no matter which processes fail and how they fail (even if most processes are malicious). However, it guarantees wait-freedom only if the writer is correct or no reader is malicious. 2 So if the readers are subject to crash failures only, the implementation is wait-free even if the writer is malicious. Note that the above impossibility and matching possibility results (1) and (2) imply the simpler results (A) and (B) that we stated earlier for processes that are (coarsely) characterized as either correct or faulty. We also consider the problem of implementing a [1, n]-register from atomic [1,1]-registers in systems where processes are subject to Byzantine failures, but they can use unforgeable signatures. In sharp contrast to the above results, we show that in such systems there is an implementation of [1, n]-register from atomic [1,1]-registers that is linearizable and wait-free no matter how many processes fail and how they fail.

Result techniques
The techniques that we used to obtain our possibility and impossibility results (for the "no signatures" case) are also a significant contribution of this paper.
To prove the impossibility result (1), one cannot use a standard partitioning argument: all the processes except the writer are given atomic [1, n]-registers that all processes can read, and the writer is given a [1, n − 1]-register that all the readers except one can read; thus it is clear that the system cannot be partitioned.
So to prove this result we use an interesting reductio ad absurdum technique. Starting from an alleged implementation of [1, n]-register from [1, n − 1]-registers, we consider a run where the implemented register is initialized to 0, the writer completes a write of 1, and then a reader reads 1. By leveraging the facts that: (1) in each step the writer can read or write only [1, n − 1]-registers, (2) the writer may crash, (3) one of the readers may be malicious, (4) and there are at least 3 readers, we are able to successively remove every read or write step of the writer (one by one, starting from its last write operation) in a way that maintains the property that some correct reader reads 1 and at most one process in the run is malicious. As we successively remove the steps of the writer, the identity of the process that reads 1, and the identity of the process that may be malicious, keep changing. By continuing this process, we end up with a run in which the writer takes no steps, and yet a correct reader reads 1.
Note that this proof is reminiscent of the impossibility proof for the "Two generals' Problem" in message-passing systems [7]. In that proof, one leverages the possibility of message losses to successively remove one message at a time. The proof given here is much more elaborate because it leverages the subtle interaction between crash and malicious failures that may occur at different processes.
For the matching possibility result (2), we solve the problem of implementing a [1, n]-register from [1, 1]-registers with a recursive algorithm: intuitively, we first give an algorithm to implement a [1, n]-register using [1, n−1]-registers, rather than only [1, 1]-registers, and then recurse till n = 2. We do so because the recursive step of implementing a [1, n]-register using [1, n−1]-registers, is significantly easier than implementing a [1, n]-register using only [1,1]-registers. This is explained in more detail in Section 5.1.

Model Sketch
We consider systems with asynchronous processes that communicate via single-writer registers and are subject to Byzantine failures. Recall that a single-writer n-reader register is denoted as a [1, n]-register; the n readers are distinct from the writer.

Process failures
A process that is subject to Byzantine failures can behave arbitrarily. In particular, it may deviate from the algorithm it is supposed to execute, or just stop this execution prematurely, i.e., crash. To distinguish between these two types of failures, we partition processes as follows: Processes that do not fail, i.e., correct processes. Processes that fail, i.e., faulty processes. Faulty processes are divided into two groups: processes that just crash, and the remaining processes, which we call malicious.

Atomic and implemented registers
A register is atomic if its read and write operations are instantaneous (i.e., indivisible); each read must return the value of the last write that precedes it, or the initial value of the register if no such write exists. Roughly speaking, the implementation of a register from a set of "base" registers is given by read/write procedures that each process can execute to read/write the implemented register; these procedures can access the given base registers (which, intuitively, may be less "powerful" than the implemented register). So each operation on an implemented register spans an interval that starts with an invocation (a procedure call) and completes with a corresponding response (a value returned by the procedure). A register implementation is wait-free [2,9,13] if it guarantees that every operation invoked by a correct process completes with a response in a finite number of steps.

Linearizability of register implementations
Unless we explicitly state otherwise, all the register implementations that we consider are linearizable [10]. Intuitively, linearizability requires that every operation on an implemented object appears as if it took effect instantaneously at some point (the "linearization point") in its execution interval.
As noted by [6,15], however, the precise definition of linearizability depends on whether processes can only crash, or they can also fail in a "Byzantine way". We now explain this for register implementations.
In systems with only crash failures. It is well-known that a single-writer multi-reader register implementation is linearizable if and only if it satisfies two simple properties. To define these properties precisely, we first define what it means for two operations to be concurrent or for one to precede the other. We say that a write operation w immediately precedes a read operation r if w precedes r, and there is no write operation w ′ such that w precedes w ′ and w ′ precedes r.
Let v 0 be the initial value of the implemented register, and v k be the value written by the k-th write operation of the writer w (this is well-defined because we make the standard assumption that each process applies operations sequentially). In systems with Byzantine failures. The above definitions do not quite work for systems with Byzantine failures. For example, it is not clear what it means for a writer w of an implemented register to "write a value v" if w is malicious, i.e., if w deviates from the write procedure that it is supposed to execute; similarly, if a reader r is malicious it is not clear what it means for r to "read a value v". The definition of linearizability for systems with Byzantine failures avoids the above issues by restricting the linearization requirements to processes that are not malicious. More precisely: ▶ Definition 3 (Register Linearizability). In a system with Byzantine process failures, an implementation of a [1, n]-register is linearizable if and only if the following holds. If the writer is not malicious, then: Property 1 [Reading a "current" value] If a read operation r by a process that is not malicious returns the value v then: there is a write v operation that immediately precedes r or is concurrent with r, or v = v 0 and no write operation precedes r.

Property 2 [No "new-old" inversion]
If two read operations r and r ′ by processes that are not malicious return values v k and v k ′ , respectively, and r precedes r ′ , then k ≤ k ′ .
Note that if the writer is correct or only crashes, then readers that are correct or only crash are required to read "current" values and also avoid "new-old" inversions. So in systems where faulty processes can only crash, Definition 3 reduces to Definition 2.
Cohen and Keidar were the first to define linearizability for arbitrary objects in systems with Byzantine failures [6], and their definition generalizes the definition of linearizability for [1, n]-registers given by Mostéfaoui et al. in [15]. Definition 3 is consistent with both.
We now describe the results of this paper. Because of space limitations, some of the proofs are omitted here; they can be found in [11].

Impossibility result
We now prove that in a system with n + 1 Byzantine processes, if the writer and one of the n readers can be faulty, then there is no wait-free linearizable implementation of a [1, n]-register from atomic [1, n − 1]-registers. In fact, by dividing faulty processes into those that can only crash and those that can be malicious (as defined in Section 3), we show the following stronger result. Proof. Let n ≥ 3. Suppose, for contradiction, that there is a wait-free linearizable implementation I of a [1, n]-register R from atomic [1, n − 1]-registers, in a system where the writer w of R can crash and one of the n readers of R can be malicious. We now construct a sequence of executions of I that leads to a contradiction. In all these executions, the initial value of the implemented R is 0, the writer w invokes only one operation into R, namely a write of 1, and each reader reads R at most once (i.e., R is only a "one-shot" binary register). Moreover, in each of these executions the writer is not malicious (it may only crash) and there is at most one malicious reader; the other n − 1 readers are correct. Since I is a linearizable register implementation and the writer of the register is not malicious, these executions of I must satisfy Properties 1 and 2 of Definition 3.
Let S be the following execution of I (see Figure 1): The writer w is correct. All the readers take no steps. The writer w invokes a write 1 operation on R. Let s 0 denote the invocation step, and let t 0 w be the time when s 0 occurs. This step is "local" to w, i.e., it does not invoke any shared register operations. During this write operation, w executes a sequence of steps s 1 , ..., s m such that each step s i is either the reading or the writing of an atomic [1, n − 1]-register. Let R i denote the register that w writes or reads in step s i . Let t i w be the time when s i occurs. Since I is a wait-free implementation and w is correct, w completes its write operation. Let s m+1 denote the response step, and let t m+1 w be the time when s m+1 occurs. Like s 0 , this step is also "local" to w.
▶ Definition 5. For all i, 0 ≤ i ≤ m + 1, the step s i of the writer w is invisible to a reader x if: (1) s i is the invocation step s 0 , (2) s i is the response step s m+1 , (3) s i is the reading of an atomic register, or (4) s i is the writing to an atomic register that is not readable by x.
Since there are n readers, and the registers that w uses are atomic [1, n − 1]-registers, every write by w into one of these registers is invisible to one of the readers. So: ▶ Observation 6. For all 0 ≤ k ≤ m + 1, step s k is invisible to at least one of the n readers. ▶ Definition 7. For every k, 0 ≤ k ≤ m + 1, an execution of I has property P k if the following holds: 1. The writer w behaves exactly as in S up to and including time t k w ; then it crashes and takes no steps after time t k w . So, w executes steps s 0 , s 1 , . . . , s k and then crashes.

There is a reader x that is correct and such that:
Step s k is invisible to x. After time t k w , process x starts and completes a read operation on R that returns 1.

3.
There is a set Z of n − 2 distinct readers that are correct and take no steps.

Figure 2
An execution with property P k .

On Implementing SWMR Registers from SWSR Registers
Note that since n ≥ 3, the set Z is not empty. Also note that while the property P k requires the n − 1 readers in {x} ∪ Z to be correct, P k does not restrict the behavior of the remaining reader; in particular, it may be correct or malicious, and it may or may not take steps. An execution of I with property P k is shown in Figure 2. In this figure and all the subsequent ones, correct readers are in black font, while the reader that may be malicious is colored red; the steps that this process may have taken are not shown in the figure. The " / ∈ x" on top of a step s i means that s i is invisible to the reader x. The symbol ✖ indicates where the crash of the writer w occurs.
For every k, 0 ≤ k ≤ m + 1, there is an execution of I that has property P k .
Proof. We prove the claim by a backward induction on k, starting from k = m + 1.
Base Case. k = m + 1. Consider the following execution denoted A m+1 (Figure 3): The writer w behaves as in execution S up to and including time t m+1 w ; then it crashes. A reader q is correct. After time t m+1 w , q starts a read operation on R. Since I is a wait-free implementation, q completes its read operation. Since w is not malicious, and the write operation by w immediately precedes the read operation by q, by the linearizability of I, the read operation by q returns 1. There is a set Z of n − 2 readers that are correct and take no steps, exactly as in S. p is the remaining reader.
Since s m+1 is a response step, it is invisible to q. So it is clear that A m+1 has property P m+1 .

Induction
Step. Let k be such that 1 ≤ k ≤ m + 1. Suppose there is an execution A k of I that has property P k (this is the induction hypothesis). We now show that there is an execution A k−1 of I that has property P k−1 . We consider two cases, namely, k > 1 and k = 1.
Case k > 1. Since execution A k of I satisfies P k , the following holds in A k (see Figure 4): The writer w behaves as in execution S up to and including time t k w ; then it crashes. There is a reader q that is correct such that step s k is invisible to q. After time t k w , q starts and completes a read operation on R that returns 1. There is a set Z of n − 2 readers that are correct and take no steps, exactly as in S. p is the remaining reader.
Then the following execution B k−1 of I also exists ( Figure 5): B k−1 is exactly like A k except that w crashes just before taking step s k (so B k−1 is just A k with the step s k "removed"). B k−1 is possible because: (1) even though p may have "noticed" the removal of step s k , p may be malicious (all other readers are correct in this execution), and (2) q cannot distinguish between A k and B k−1 because s k is invisible to q, and p and all the readers in Z behave as in A k .
Since k > 1, A k has a step s k−1 ̸ = s 0 . There are two cases: Case 1. s k−1 is invisible to q. Then B k−1 is an execution of I that has the property P k−1 , as we wanted to show. Case 2. s k−1 is visible to q. Then s k−1 is invisible to p or to some reader in Z . Let r be any process in Z . We construct the execution C r k−1 of I shown in Figure 6: C r k−1 is a continuation of B k−1 where, after the correct reader q reads 1, malicious p wipes out any trace of the write steps that it has taken so far, and then a correct process r ∈ Z reads 1 (this is the only value that r can read, since correct q previously read 1). More precisely: C r k−1 is an extension of B k−1 . After the correct reader q completes its read operation on R, q takes no steps. All the readers in Z − {r} are correct and take no steps 3 . After q completes its read operation, p resets all the atomic registers that it can write to their initial values. Process p can do so because it may be malicious (all other readers are correct in this execution). Let t r p be the time when p completes all the register resettings. A correct reader r starts a read operation on R after time t r p . It takes no steps before this read. Since I is a wait-free implementation, r completes its read operation. Since w is not malicious and the read operation by correct q returns 1 and precedes the read operation by r, by the linearizability of I, the read operation by r returns 1.
We can now construct the following execution D r k−1 of I (Figure 7). D r k−1 is obtained from C r k−1 by removing all the steps of p. Despite this removal, q behaves the same as in C r k−1 because q is now malicious. Correct r also behaves as in C q k−1 because it cannot see the removal of p's steps: in both C r k−1 and D r k−1 , r does not "see" any steps of p. More precisely in D r k−1 : w behaves exactly as in C r k−1 . p is correct and takes no steps. So all its registers retain their initial value. All the readers in Z − {r} are correct and take no steps as in C r k−1 . q behaves the same as in C r k−1 . This is possible because even though q may have "noticed" the removal of p's steps, q may be malicious (all other readers are correct in this execution). After possibly malicious q "reads" 1, the correct reader r starts and completes a read operation on R. Since r cannot see the removal of p's steps, and q and all the readers in Z − {r} behave the same as in C r k−1 , r cannot distinguish between D r k−1 and C r k−1 . So the read operation by r returns 1 as in C r k−1 .
Note that if s k−1 is invisible to process r, then the execution D r k−1 of I has property P k−1 .
Recall that (1) the process r above is an arbitrary process in Z , and (2) s k−1 is invisible to p or to some reader r ′ ∈ Z. So there are two cases: Subcase 2a. s k−1 is invisible to some reader r ′ ∈ Z. In the above we proved that the execution D r ′ k−1 of I has property P k−1 , as we wanted to show. Subcase 2b. s k−1 is invisible to p. In this case we construct the continuation E r k−1 of D r k−1 shown in Figure 8: after r reads 1, malicious process q wipes out any trace of the write steps that it has taken so far (by reinitializing its registers), and then correct process p applies a read operation to R. By wait freedom, this read operation by p must complete.
Since w is not malicious and correct r previously read 1, by linearizability, this read operation by p must return 1.
Finally, we construct the execution F r k−1 of I by removing all the steps of q from E r k−1 (see Figure 9); so q (which was malicious in E r k−1 ) is now a correct process that takes no steps. Despite this removal, r behaves the same as in E r k−1 because r (which was correct in E r k−1 ) may now be malicious. Moreover, correct p also behaves as in E r k−1 because it cannot see the removal of q's steps: in both E r k−1 and F r k−1 , p does not "see" any steps of q. So the read operation by p returns 1 as in E r k−1 . Note that, since s k−1 is invisible to p, F r k−1 is an execution of I that has property P k−1 .
3 If n = 3, then the set Z − {r} is empty.

36:10 On Implementing SWMR Registers from SWSR Registers
Case k = 1. By the induction hypothesis, there is an execution A 1 as follows ( Figure 10): The writer w behaves exactly as in S up to and including time t 1 w ; then it crashes. After time t 1 w , a correct reader q starts and completes a read operation on R that returns 1. Furthermore, s 1 is invisible to q. There is a set Z of n − 2 readers that are correct and take no steps. p is the remaining reader.
Then the following execution A 0 of I also exists ( Figure 11): A 0 is like A 1 except that w crashes just before taking step s 1 (so A 0 is just A 1 with the step s 1 "removed"). A 0 is possible because: (1) even though p may have "noticed" the removal of step s 1 , p may be malicious (all other readers are correct in this execution), and (2) q cannot distinguish between A 0 and A 1 because s 1 is invisible to q, and p and all the readers in Z behave as in A 1 . Since s 0 is an invocation step, it is invisible to q. It is now easy to see that execution A 0 of I has property P 0 , as we wanted to show. ◁ By the claim that we just proved, implementation I has an execution A 0 with property P 0 . By this property, in A 0 process w crashes immediately after the invocation step s 0 of its write 1 operation, and some correct reader x later reads the value 1. Since the invocation step s 0 is invisible to all the readers (because it does not involve writing any of the shared registers), there is an execution of A ′ 0 of I where: (1) w does not take any step at all (so it is not malicious), and (2) a correct reader x reads 1 exactly as in A 0 (because no reader can distinguish between A 0 and A ′ 0 ). This execution A ′ 0 of I violates the linearizability of I. ◀ It is easy to verify that the above proof holds (without any change) even if all the readers have atomic [1, n]-registers that they can write and all processes can read. Thus:

Register implementation algorithm
We now give an implemention of a [1, n]-register from atomic [1, 1]-registers in systems with Byzantine process failures; this implementation is linearizable, and it is wait-free provided the writer of the register or any number of the readers but not both can be faulty. More precisely, it is a valid implementation as defined below.

▶ Definition 9. A register implementation is valid if it satisfies the following:
It is linearizable. It is wait-free if the writer is correct or no reader is malicious.
Note that, when executed in a system where processes can only crash, a valid register implementation is linearizable and wait-free (unconditionally).

Some difficulties to overcome
Note that in a system with Byzantine process failures, implementing a [1, n]-register from [1, 1]-registers is non-trivial, even if the writer can only crash. To see this, we now illustrate some of the issues that arise. First note that with [1,1]-registers the writer cannot simultaneously inform all the readers about a new write. So different readers may have different views of whether there is a write in progress: some readers may not see it, some readers may see it as still in progress, while other readers may see it as having completed. Thus readers must communicate with each other to avoid "new-old" inversions in the values they read. With non-Byzantine failures, readers can easily coordinate their reads because they can trust the information they pass to each other. With Byzantine failures, however, readers cannot blindly trust what other readers tell them.
For example, suppose a reader q is aware that a write v operation is in progress (say because the writer w directly "told" q about it via the register that they share). To avoid a "new-old" inversion, q checks whether any other reader q ′ has already read v (because it is possible that from q ′ 's point of view, the write of v already completed). Suppose some q ′ "warns" q that it has already read the new value v, and so q also reads v. But what if q ′ is malicious and "lied" to q (and only to q) about having read v? Note that q may be the only correct reader currently aware that the write of v is in progress (say because w is slow). Now suppose that a reader q ′′ that is not aware of the write of v also wants to read: if q ′′ reads the old value of the register this creates a "new-old" inversion with the newer value v that q previously read; but if q ′′ reads v because q warns q ′′ that it had read v, then q ′′ may be reading a value v that was never written by the correct writer w: q itself could be malicious and could have "lied" about reading v!
The above is only one of many possible scenarios illustrating why it is not easy to implement a [1, n]-register from [1, 1]-registers when some readers can be malicious, even if the writer itself is not malicious.

A recursive solution
To simplify this task, we do not directly implement a [1, n]-register using only [1, 1]-registers. Instead, we first give an implementation I n of a [1, n]-register that uses some [1, n−1]-registers together with some [1, 1]-registers. Then, by replacing the [1, n − 1]-registers with I n−1 implementations, we get an implementation of the [1, n]-register that uses some [1, n − 2]-registers and some [1, 1]-registers. By recursing down to n = 2, this gives an implementation of the [1, n]-register that uses only [1,1]-registers. In other words, we can implement a [1, n]-register from [1, 1]-registers with a recursive construction that gradually reduces the number of readers of the base registers that it uses (all the way down to 1). We now describe this recursive implementation and prove its correctness.

Implementing a [1,n]-register from [1,n-1]-registers
Algorithm 1 gives an implementation I n of a [1, n]-register that is writable by a process w and readable by every process in {p} ∪ Q, where p is an arbitrary reader and all remaining n − 1 readers are in Q. We distinguish p from the other readers in Q because p and q ∈ Q use different procedures for reading the implemented [1, n]-register. I n uses two kinds of registers: atomic [1, 1]-registers and implemented [1, n − 1]-registers. We will show that I n is valid under the assumption that the [1, n − 1]-register implementations that it uses are also valid (and therefore linearizable).
Notation. Recall that if R is an atomic register, all operations applied to R are instantaneous, whereas if R is an implemented register, each operation spans an interval of time, from an invocation to a response. However, since we assume that the [1, n−1]-register implementations that I n uses are valid and therefore linearizable, we can think of each operation on an implemented [1, n − 1]-register as being atomic, i.e., as if it takes effect instantaneously at D I S C 2 0 2 2 Algorithm 1 Implementation In of a [1, n]-register writable by (an arbitrary) process w and readable by the n processes in {p} ∪ Q, for n ≥ 2. It uses two [1, n − 1]-registers and some [1, 1]-registers.
Description. The implementation I n of a [1, n]-register from [1, n − 1]-registers consists of two procedures, namely Write() for the writer w, and Read() for each reader r in {p} ∪ Q.
To write a value u, the writer w executes Write(u). If u is the k-th value written by w, Write(u) first forms the unique tuple ⟨k, u⟩ and then it calls the lower-level write procedure w(⟨k, u⟩) to write this tuple. Intuitively, Write() tags the values that it writes with a counter value to make them unique and to indicate in which order they are written.
To read a value, a reader r ∈ {p} ∪ Q calls Read(), and this in turn calls a lower-level read procedure r r () that reads tuples written by w(). There are two version of the procedure r r (): one used when r = p and one used when r ∈ Q. If r r () returns a tuple of the form ⟨j, v⟩, then Read() strips the counter j from the tuple and returns the value v as the value read (otherwise Read() returns ⊥ to indicate a read failure).
Thus the lower-level procedures w(), r p (), and r q () for each q ∈ Q, are executed to write and read unique tuples of the form ⟨k, u⟩. We now describe how these procedures work.
To execute w(⟨k, u⟩), process w first writes (prepare, last_written, ⟨k, u⟩) in the R wp register that p can read, and then in the R wQ register that every process in Q can read; last_written is the last tuple written by w before ⟨k, u⟩ (so last_written = ⟨k − 1, u ′ ⟩ for some u ′ ). Then, w writes (commit, ⟨k, u⟩) into R wp and then into R wQ . To execute r p (), process p reads R wp (line 14). If p reads (commit, ⟨k, u⟩) with a k at least as big as those it saw before, it returns ⟨k, u⟩ as the tuple read (line 17); just before doing so, however, it writes ⟨k, u⟩ in the R pQ register that every process q ∈ Q can read (line 15): intuitively, this is to "warn" them that p read a "new" tuple, to help avoid "new-old" inversion in the tuples read. If p reads (prepare, last_written, ⟨k, u⟩) (line 18), then it returns last_written as the tuple read (without giving any "warning" about this to processes in Q). If p reads anything else from R wp , then it returns ⊥ (the writer is surely malicious). To execute r q (), process q ∈ Q reads R wQ . If q reads (commit, ⟨k, u⟩) (line 21), it just returns ⟨k, u⟩ as the tuple read in line 22 (without "warning" other processes). If q reads (prepare, last_written, ⟨k, u⟩) (line 23), then q cannot simply return last_written as the tuple read: this is because p could have already read (commit, ⟨k, u⟩) from R wp and so p could have already read the "newer" tuple ⟨k, u⟩ with r p (). So q must determine whether to return last_written or ⟨k, u⟩. To do so, q forks two threads and executes them in parallel (we will explain why below). 5 In Thread 1, process q keeps reading R wQ : if it ever reads (commit, ⟨k ′ , −⟩) with k ′ ≥ k, or (prepare, −, ⟨k ′ , −⟩) with k ′ > k, it simply returns ⟨k, u⟩ as the tuple read. Note that if the writer w is correct, then q cannot spin forever in this thread without returning ⟨k, u⟩.
In Thread 2, process q first reads the register R pQ to see whether p "warned" processes in Q that it read a tuple at least as "new" as ⟨k, u⟩.
If q sees that R pQ contains a tuple at least as "new" as ⟨k, u⟩ (line 30), then q returns ⟨k, u⟩ as the tuple read (line 32); but before doing so, q successively writes ⟨k, u⟩ in each register R qq ′ such that q ′ ∈ Q (line 31): intuitively, this is to "warn" each process in Q that q read this "new" tuple.
Otherwise, q reads every R q ′ q register to avoid a new-old inversion with any tuple read by any process q ′ ∈ Q: if q sees that some R q ′ q contains a tuple at least as "new" as ⟨k, u⟩ (line 33), then q reads R pQ again (line 34) (so q does not simply "trust" q ′ and return ⟨k, u⟩!). If q sees that R pQ contains a tuple at least as "new" as ⟨k, u⟩ (line 34), then q returns ⟨k, u⟩ as the tuple read (line 36); and before doing so q successively writes ⟨k, u⟩ to every register R qq ′ such that q ′ ∈ Q (line 35). Finally, if q does not see that R pQ or R qq ′ contain a tuple at least as "new" as ⟨k, u⟩ (in lines 30 and 33), then q returns last_written (line 37).

Why two parallel threads?
In a nutshell, this is to guarantee the wait-freedom of I n in runs where the writer is correct or no reader is malicious. This is required for our implementation to be valid. It turns out that: (A) if only Thread 1 is executed, then a faulty writer can block correct readers even if no reader is malicious, and (B) if only Thread 2 is executed, then malicious readers can block correct readers from returning any value in this thread even if the writer is correct.
But if the writer is correct or no reader is malicious, we can show that every read operation by a correct reader is guaranteed to complete with a return value in one of the two threads.
It is easy to see why a faulty writer (even one that just crashes) may block a correct reader in Thread 1. We now explain how malicious readers may impede correct readers in Thread 2.
In Thread 2 readers must read R pQ at least once (in line 30). Recall that (a) R pQ is an implemented [1, n − 1]-register, and (b) we are only assuming that this implementation is valid. In particular, if the writer p of R pQ crashes and some readers of R pQ are malicious, the implementation of R pQ does not guarantee the wait-freedom of its read operations. In other words, if p crashes and some readers of R pQ are malicious, a correct reader q may block while trying to read R pQ ! Malicious readers may also prevent a correct reader q from reading any tuple in Thread 2 as follows. When q executes r q () the following can occur: (1) in line 33, q sees that some R q ′ q contains ⟨k ′ , −⟩ with k ′ ≥ k , but (2) in line 34 q sees that R pQ does not contain ⟨k ′ , −⟩ with k ′ ≥ k. We can show that this can occur only if at least one of p or q ′ is malicious. Note that if (1) and (2) indeed occur, then q terminates Thread 2 without returning any tuple (because the if of line 34 does not have a corresponding else).
The correctness of the implementation I n given by Algorithm 1 is stated in Theorem 10. The proof of this theorem is given in [11]. It's worth noting that for the case n = 2, there is a simple implementation I 2 ′ that is stronger than the I 2 implementation given by Algorithm 1: in contrast to I 2 , I 2 ′ is unconditionally wait-free. The implementation I 2 ′ is given by Algorithm 3 in Appendix A.
Note that Algorithm 3 is a simple version of Algorithm 1: the set of readers Q now contains only one process q, and so preventing new-old inversions is much easier. Since I n is valid, it is linearizable (no matter which processes fail and how); and it is waitfree provided the writer is correct or no reader is malicious. This matches the impossibility result given by Theorem 4 in Section 4. Algorithm 2 Implementation Is of a [1, n]-register writable by process w and readable by a set P of n processes in a system with unforgeable signatures. Is uses atomic [1, 1]-registers.

Atomic Registers
For every processes i and j: R ij : atomic [ for every process i ∈ P do 9: R wi ← ⟨k, u⟩w ▷ ⟨k, u⟩ signed by w 10: return done r(): ▷ executed by any reader p ∈ P 11: tuples ← ∅ 12: for every process i ∈ {w} ∪ P do 13: if R ip = ⟨ℓ, val⟩w for some ⟨ℓ, val⟩ validly signed by w then 14: tuples ← tuples ∪ {⟨ℓ, val⟩w} 15: ⟨k, u⟩w ← tuple ⟨ℓ, val⟩w with maximum sequence number ℓ in tuples 16: for every process i ∈ P do 17: R pi ← ⟨k, u⟩w 18: return ⟨k, u⟩w 6 Implementation for systems with digital signatures Algorithm 2 gives a linearizable and wait-free implementation I s of a [1, n]-register that is writable by process w and readable by a set P of n processes. I s uses unforgeable signatures of processes (actually only w does) and atomic [1,1]-registers between each pair of processes. As in Algorithm 1, to write a value u the writer w first adds a counter k to form a tuple ⟨k, u⟩. It then signs ⟨k, u⟩, and the signed tuple is denoted ⟨k, u⟩ w . As before, the actual write and read operations are done by lower-level procedures w() and r(), which work as follows: To execute w(⟨k, u⟩ w ), the writer w simply writes ⟨k, u⟩ w in R wi for every process i.
To execute r(), the process p first reads the [1, 1]-register R ip of every process i to collect a set tuples of the tuples with valid signature of w. Then p selects the tuple ⟨k, u⟩ w with maximum sequence number k in tuples, and return this tuple; but before doing so p writes ⟨k, u⟩ w into every [1, 1]-register R pi to notify every process i that it read this tuple.
The correctness of the implementation I s given by Algorithm 2 is stated in Theorem 13. The proof of this theorem is given in [11].
▶ Theorem 13. Consider a system where processes are subject to Byzantine failures and can use unforgeable signatures. For every n ≥ 2, I s is a wait-free linearizable implementation of a [1, n]-register from atomic [1,1]-registers that tolerates any number of faulty processes.

Concluding remarks
The implementation of registers from weaker registers is a basic problem in distributed computing that has been extensively studied in the context of processes with crash failures.
In this paper, we investigated this problem in the context of Byzantine processes failures, with and without process signatures. We first proved that there is no wait-free linearizable implementation of a [1, n]-register from atomic [1, n − 1]-registers. In fact, we showed that this impossibility holds even if every process except the writer can use atomic [1, n]-registers, and even under the assumption that the writer can only crash and at most one reader can be malicious. This is in sharp contrast to the situation in systems with crash failures only, where there is a wait-free linearizable implementation of a [1, n]-register even from safe [1, 1]-registers [14].
In light of this strong impossibility result, we gave an implementation of a [1, n]-register from atomic [1,1]-registers that is linearizable (intuitively, "safe") under any combination of Byzantine process failures, but is wait-free (intuitively, "live") only under the assumption that the writer is correct or no reader is malicious; this matches the impossibility result. We also gave an implementation that uses process signatures, and is wait-free and linearizable under any number and combination of Byzantine process failures.
Perhaps surprisingly, none of the above results refers to a ratio of faulty vs. correct processes, such as n/3 or n/2, that we typically encounter in results that involve Byzantine processes. For example, Mostéfaoui et al. [15] prove that one can implement an f -resilient [1, n]-register in message-passing systems with Byzantine process failures if and only if f < n/3. As an other example, Cohen and Keidar [6] show that if f < n/2, one can use atomic [1, n]-registers to get f -resilient implementations of reliable broadcast, atomic snapshot, and asset transfer objects in systems with Byzantine process failures.
It is worth noting that, since atomic [1, 1]-registers can simulate message-passing channels, one can use the f -resilient implementation of a [1, n]-register for message-passing systems given in [15], to obtain an f -resilient implementation of a [1, n]-register using atomic [1,1]-registers. But f -resilient implementations (such as the ones given in [6,15]) require every correct process to help the execution of every operation, even the operations of other processes. In contrast, with wait-free object implementations in shared-memory systems, processes that do not have ongoing operations take no steps.