Bringing back the tiny chain project of learning how block chain stuff works :3
This commit is contained in:
		
						commit
						e1d692dc1b
					
				
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| chain | ||||
| *.bin | ||||
| *.out | ||||
| socket/bin/* | ||||
| .vscode/ | ||||
							
								
								
									
										19
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| Copyright (c) 2020 Temper | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||||
| DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||||
| OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE | ||||
| OR OTHER DEALINGS IN THE SOFTWARE. | ||||
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| cc=g++ -Wall -O2 -lm | ||||
| 
 | ||||
| default: | ||||
| 	$(cc) blockchain.cpp -o chain | ||||
| 
 | ||||
							
								
								
									
										2
									
								
								bft/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								bft/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| all: | ||||
| 	gcc generals.c -O2 -Wall -pedantic -Werror -o sim.bin | ||||
							
								
								
									
										918
									
								
								bft/bft-problem.book
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										918
									
								
								bft/bft-problem.book
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,918 @@ | ||||
| The Byzantine Generals Problem | ||||
| LESLIE LAMPORT, ROBERT SHOSTAK, and MARSHALL PEASE | ||||
| SRI International | ||||
| 
 | ||||
| # Ripped to a fully text version by me: shockrah :^) | ||||
| 
 | ||||
| Reliable computer systems must handle malfunctioningcomponents that give conflicting information | ||||
| to different parts of the system. This situation can be expressed abstractly in terms of a group of | ||||
| generals of the Byzantine army camped with their troops around an enemy city. Communicatingonly | ||||
| by messenger, the generals must agree upon a common battle plan. However, one or more of them | ||||
| may be traitors who will try to confuse the others. The problem is to find an algorithm to ensure that | ||||
| the loyal generals will reach agreement. It is shown that, using only oral messages, this problem is | ||||
| solvable if and only if more than two-thirds of the generals are loyal; so a single traitor can confound | ||||
| two loyal generals. With unforgeable written messages, the problem is solvable for any number of | ||||
| generals and possible traitors. Applications of the solutions to reliable computer systems are then | ||||
| discussed. | ||||
| Categories and Subject Descriptors: C.2.4. [Computer-Communication Networks]: Distributed | ||||
| Systems--network operating systems; D.4.4 [Operating Systems]: CommunicationsManagement-- | ||||
| network communication; D.4.5 [Operating Systems]: Reliability--fault tolerance | ||||
| General Terms: Algorithms, Reliability | ||||
| Additional Key Words and Phrases: Interactive consistency | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                                                             / | ||||
| 
 | ||||
| 
 | ||||
| 1. INTRODUCTION | ||||
| A reliable computer system must be able to cope with the failure of one or more | ||||
| of its components. A failed component may exhibit a type of behavior that is | ||||
| of tenover looked -- namely, sending conflicting information to different parts of | ||||
| thesystem.Theproblemofcopingwiththistypeoffailureisexpressedabstractly | ||||
| astheByzantineGeneralsProblem.Wedevotethemajorpartofthepapertoa | ||||
| discussionofthisabstractproblemandconcludebyindicatinghowoursolutions | ||||
| canbeusedinimplementingareliablecomputersystem. | ||||
| WeimaginethatseveraldivisionsoftheByzantinearmyarecampedoutside | ||||
| anenemycity,eachdivisioncommandedbyitsowngeneral.Thegeneralscan | ||||
| communicate with one another only by messenger. After observing the enemy, | ||||
| t h e y m u s t d e c i d e u p o n a c o m m o n p l a n of a c t i o n . H o w e v e r , s o m e of t h e g e n e r a l s | ||||
| 
 | ||||
| This research was supported in part by the National Aeronautics and Space Administration under | ||||
| contract NAS1-15428 Mod. 3, the Ballistic Missile Defense Systems Command under contract | ||||
| DASG60-78-C-0046, and the Army Research Office under contract DAAG29-79-C-0102. | ||||
| Authors' address: Computer Science Laboratory, SRI International, 333 Ravenswood Avenue, Menlo | ||||
| Park, CA 94025. | ||||
| Permission to copy without fee all or part of this material is granted provided that the copies are not | ||||
| made or distributed for direct commercial advantage, the ACM copyright notice and the title of the | ||||
| publication and its date appear, and notice is given that copying is by permission of the Association | ||||
| for Computing Machinery. To copy otherwise, or to republish, requires a fee and/or specific | ||||
| permission. | ||||
| © 1982 ACM 0164-0925/82/0700-0382 $00.75 | ||||
| ACM Transactionson ProgrammingLanguagesand Systems,Vol.4, No. 3, July 1982,Pages 382-401. | ||||
|                                                 The Byzantine Generals Problem                     383 | ||||
| 
 | ||||
| may be traitors, trying to prevent the loyal generals from reaching agreement. | ||||
| The generals must have an algorithm to guarantee that | ||||
| 
 | ||||
|  A. All loyal generals decide upon the same plan of action. | ||||
| 
 | ||||
|    The loyal generals will all do what the algorithm says they should, but the | ||||
| traitors may do anything they wish. The algorithm must guarantee condition A | ||||
| regardless of what the traitors do. | ||||
|    The loyal generals should not only reach agreement, but should agree upon a | ||||
| reasonable plan. We therefore also want to insure that | ||||
| 
 | ||||
| B. A small number of traitors cannot cause the loyal generals to adopt a bad | ||||
|    plan. | ||||
| 
 | ||||
|    Condition B is hard to formalize, since it requires saying precisely what a bad | ||||
| plan is, and we do not attempt to do so. Instead, we consider how the generals | ||||
| reach a decision. Each general observes the enemy and communicates his obser- | ||||
| vations to the others. Let v(i) be the information communicated by the ith | ||||
| general. Each general uses some method for combining the values v (1) . . . . . v (n) | ||||
| into a single plan of action, where n is the number of generals. Condition A is | ||||
| achieved by having all generals use the same method for combining the infor- | ||||
| mation, and Condition B is achieved by using a robust method. For example, if | ||||
| the only decision to be made is whether to attack or retreat, then v(i) con be | ||||
| General i's opinion of which option is best, and the final decision can be based | ||||
| upon a majority vote among them. A small number of traitors can affect the | ||||
| decision only if the loyal generals were almost equally divided between the two | ||||
| possibilities, in which case neither decision could be called bad. | ||||
|    While this approach may not be the only way to satisfy conditions A and B, it | ||||
| is the only one we know of. It assumes a method by which the generals | ||||
| communicate their values v (i) to one another. The obvious method is for the ith | ||||
| general to send v (i) by messenger to each other general. However, this does not | ||||
| work, because satisfying condition A requires that every loyal general obtain the | ||||
| same values v(1) . . . . . v(n), and a traitorous general may send different values to | ||||
| different generals. For condition A to be satisfied, the following must be true: | ||||
| 1. Every loyal general must obtain the same information v (1) . . . . , v (n). | ||||
|   Condition 1 implies that a general cannot necessarily use a value of v(i) | ||||
| obtained directly from the ith general, since a traitorous ith general may send | ||||
| different values to different generals. This means that unless we are careful, in | ||||
| meeting condition 1 we might introduce the possibility that the generals use a | ||||
| value of v (i) different from the one sent by the ith general--even though the ith | ||||
| general is loyal. We must not allow this to happen if condition B is to be met. For | ||||
| example, we cannot permit a few traitors to cause the loya~ generals to base their | ||||
| decision upon the values " r e t r e a t " , . . . , "retreat" if every loyal general sent the | ||||
| value "attack". We therefore have the following requirement for each i: | ||||
| 2. If the ith general is loyal, then the value that he sends must be used by every | ||||
|    loyal general as the value of v (i). | ||||
| 
 | ||||
|    We can rewrite condition I as the condition that for every i (whether or not the | ||||
| ith general is loyal), | ||||
| 1'. Any two loyal generals use the same value of v(i). | ||||
|    Conditions 1' and 2 are both conditions on the single value sent by the ith | ||||
| general. We can therefore restrict our consideration to the problem of how a | ||||
| single general sends his value to the others. We phrase this in terms of a | ||||
| commanding general sending an order to his lieutenants, obtaining the following | ||||
| problem. | ||||
|   Byzantine Generals Problem. A commanding general must send an order to | ||||
| his n - 1 lieutenant generals such t hat | ||||
| IC1. All loyal lieutenants obey the same order. | ||||
| IC2. If the commanding general is loyal, then every loyal lieutenant obeys the | ||||
|      order he sends. | ||||
|   Conditions IC1 and IC2 are called the interactive consistency conditions. Note | ||||
| that if the commander is loyal, then IC1 follows from IC2. However, the com- | ||||
| mander need not be loyal. | ||||
|   To solve our original problem, the ith general sends his value of v(i) by using | ||||
| a solution to the Byzantine Generals Problem to send the order "use v (i) as my | ||||
| value", with the other generals acting as the lieutenants. | ||||
| 
 | ||||
| 2. IMPOSSIBILITY RESULTS | ||||
| T h e Byzantine Generals Problem seems deceptively simple. Its difficulty is | ||||
| indicated by the surprising fact that if the generals can send only oral messages, | ||||
| then no solution will work unless more than two-thirds of the generals are loyal. | ||||
| In particular, with only three generals, no solution can work in the presence of a | ||||
| single traitor. An oral message is one whose contents are completely under the | ||||
| control of the sender, so a traitorous sender can transmit any possible message. | ||||
| Such a message corresponds to the type of message that computers normally | ||||
| send to one another. In Section 4 we consider signed, written messages, for which | ||||
| this is not true. | ||||
|    We now show that with oral messages no solution for three generals can handle | ||||
| a single traitor. For simplicity, we consider the case in which the only possible | ||||
| decisions are "attack" or "retreat". Let us first examine the scenario pictured in | ||||
| Figure 1 in which the commander is loyal and sends an "attack" order, but | ||||
| Lieutenant 2 is a traitor and reports to Lieutenant 1 that he received a "retreat" | ||||
| order. For IC2 to be satisfied, Lieutenant 1 must obey the order to attack. | ||||
|    Now consider another scenario, shown in Figure 2, in which the commander is | ||||
| a traitor and sends an "attack" order to Lieutenant 1 and a "retreat" order to | ||||
| Lieutenant 2. Lieutenant 1 does not know who the traitor is, and he cannot tell | ||||
| what message the commander actually sent to Lieutenant 2. Hence, the scenarios | ||||
| in these two pictures appear exactly the same to Lieutenant 1. If the traitor lies | ||||
|  consistently, then there is no way for Lieutenant 1 to distinguish between these | ||||
|  two situations, so he must obey the "attack" order in both of them. Hence, | ||||
|  whenever Lieutenant 1 receives an "attack" order from the commander, he must | ||||
|  obey it. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    However, a similar argument shows that if Lieutenant 2 receives a "retreat" | ||||
| order from the commander then he must obey it even if Lieutenant 1 tells him | ||||
| that the commander said "attack". Therefore, in the scenario of Figure 2, | ||||
| Lieutenant 2 must obey the "retreat" order while Lieutenant 1 obeys the "attack" | ||||
| order, thereby violating condition IC1. Hence, no solution exists for three generals | ||||
| that works in the presence of a single traitor. | ||||
|    This argument may appear convincing, but we strongly advise the reader to be | ||||
| very suspicious of such nonrigorous reasoning. Although this result is indeed | ||||
| correct, we have seen equally plausible "proofs" of invalid results. We know of no | ||||
| area in computer science or mathematics in which informal reasoning is more | ||||
| likely to lead to errors than in the study of this type of algorithm. For a rigorous | ||||
| proof of the impossibility of a three-general solution that can handle a single | ||||
| traitor, we refer the reader to [3]. | ||||
|    Using this result, we can show that no solution with fewer than 3m + 1 generals | ||||
|  can cope with m traitorsJ T he proof is by contradiction--we assume such a | ||||
| ' More precisely, no such solution exists for three or more generals, since the problem is trivial for two | ||||
| generals. | ||||
| 
 | ||||
| The solution for a group of 3m or fewer and use it to construct a three-general solution | ||||
| to the Byzantine Generals Problem that works with one traitor, which we know | ||||
| to be impossible. To avoid confusion between the two algorithms, we call the | ||||
| generals of the assumed solution Albanian generals, and those of the constructed | ||||
| solution Byzantine generals. Thus, starting from an algorithm that allows 3m or | ||||
| fewer Albanian generals to cope with m traitors, we construct a solution that | ||||
| allows three Byzantine generals to handle a single traitor. | ||||
|    The three-general solution is obtained by having each of the Byzantine generals | ||||
| simulate approximately one-third of the Albanian generals, so that each Byzan- | ||||
| tine general is simulating at most m Albanian generals. The Byzantine com- | ||||
| mander simulates the Albanian commander plus at most m - 1 Albanian | ||||
| lieutenants, and each of the two Byzantine lieutenants simulates at most m | ||||
| Albanian lieutenants. Since only one Byzantine general can be a traitor, and he | ||||
| simulates at most m Albanians, at most m of the Albanian generals are traitors. | ||||
| Hence, the assumed solution guarantees that IC1 and IC2 hold for the Albanian | ||||
| generals. By IC1, all the Albanian lieutenants being simulated by a loyal Byzan- | ||||
| tine lieutenant obey the same order, which is the order he is to obey. It is easy to | ||||
| check that conditions IC1 and IC2 of the Albanian generals solution imply the | ||||
| corresponding conditions for the Byzantine generals, so we have constructed the | ||||
| required impossible solution. | ||||
|    One might think that the difficulty in solving the Byzantine Generals Problem | ||||
| stems from the requirement of reaching exact agreement. We now demonstrate | ||||
| that this is not the case by showing that reaching approximate agreement is just | ||||
| as hard as reaching exact agreement. Let us assume that instead of trying to agree | ||||
| on a precise battle plan, the generals must agree only upon an approximate time | ||||
| of attack. More precisely, we assume that the commander orders the time of the | ||||
| attack, and we require the following two conditions to hold: | ||||
| IC1 '. All loyal lieutenants attack within 10 minutes of one another. | ||||
| IC2'. If the commanding general is loyal, then every loyal lieutenant attacks | ||||
|        within 10 minutes of the time given in the commander's order. | ||||
| (We assume that the orders are given and processed the day before the attack | ||||
| and that the time at which an order is received is irrelevant--only the attack | ||||
| time given in the order matters.} | ||||
|   Like the Byzantine Generals Problem, this problem is unsolvable unless more | ||||
| than two-thirds of the generals are loyal. We prove this by first showing that if | ||||
| there were a solution for three generals that coped with one traitor, then we could | ||||
| construct a three-general solution to the Byzantine Generals Problem that also | ||||
| worked in the presence of one traitor. Suppose the commander wishes to send an | ||||
| "attack" or "retreat" order. He orders an attack by sending an attack time of 1:00 | ||||
| and orders a retreat by sending an attack time of 2:00, using the assumed | ||||
| algorithm. Each lieutenant uses the following procedure to obtain his order. | ||||
| (1) After receiving the attack time from the commander, a lieutenant does one | ||||
|     of the following: | ||||
|       (a) If the time is 1:10 or earlier, then attack. | ||||
|       (b) If the time is 1:50 or later, then retreat. | ||||
|       (c) Otherwise, continue to step (2). | ||||
| ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
|                                                 The Byzantine Generals Problem               •     387 | ||||
| 
 | ||||
|   (2) Ask the other lieutenant what decision he reached in step (1). | ||||
|      (a) If the other lieutenant reached a decision, then make the same decision | ||||
|          he did. | ||||
|      (b) Otherwise, retreat. | ||||
| 
 | ||||
|      It follows from IC2' that if the commander is loyal, then a loyal lieutenant will | ||||
|   obtain the correct order in step (1), so IC2 is satisfied. If the commander is loyal, | ||||
|   then IC1 follows from IC2, so we need only prove IC1 under the assumption that | ||||
|   the commander is a traitor. Since there is at most one traitor, this means that | ||||
|   both lieutenants are loyal. It follows from I C I ' that if one lieutenant decides to | ||||
|   attack in step (1), then the other cannot decide to retreat in step (1). Hence, | ||||
|   either they will both come to the same decision in step (1) or at least one of them | ||||
|   will defer his decision until step (2). In this case, it is easy to see that they both | ||||
|   arrive at the same decision, so IC1 is satisfied. We have therefore constructed a | ||||
|   three-general solution to the Byzantine Generals Problem that handles one | ||||
|  traitor, which is impossible. Hence, we cannot have a three-general algorithm | ||||
|  that maintains I C I ' and IC2' in the presence of a traitor. | ||||
|     Th e method of having one general simulate m others can now be used to prove | ||||
|  that no solution with fewer than 3rn + 1 generals can cope with m traitors. T he | ||||
|  proof is similar to the one for the original Byzantine Generals Problem and is left | ||||
|  to the reader. | ||||
| 
 | ||||
|  3. A SOLUTION WITH ORAL MESSAGES | ||||
| We showed above that for a solution to the Byzantine Generals Problem using | ||||
| oral messages to cope with rn traitors, there must be at least 3m + 1 generals. We | ||||
| now give a solution that works for 3m + 1 or more generals. However, we first | ||||
| specify exactly what we mean by "oral messages". Each general is supposed to | ||||
| execute some algorithm that involves sending messages to the other generals, and | ||||
| we assume that a loyal general correctly executes his algorithm. The definition of | ||||
| an oral message is embodied in the following assumptions which we make for the | ||||
| generals' message system: | ||||
| 
 | ||||
| A1. Every message that is sent is delivered correctly. | ||||
| A2. Th e receiver of a message knows who sent it. | ||||
| A3. Th e absence of a message can be detected. | ||||
|     Assumptions A1 and A2 prevent a traitor from interfering with the communi- | ||||
|  cation between two other generals, since by A1 he cannot interfere with the | ||||
|  messages they do send, and by A2 he cannot confuse their intercourse by | ||||
|  introducing spurious messages. Assumption A3 will foil a traitor who tries to | ||||
|  prevent a decision by simply not sending messages. The practical implementation | ||||
|  of these assumptions is discussed in Section 6. | ||||
|    T h e algorithms in this section and in the following one require that each | ||||
|  general be able to send messages directly to every other general. In Section 5, we | ||||
| describe algorithms which do not have this requirement. | ||||
|    A traitorous commander may decide not to send any order. Since the lieuten- | ||||
| ants must obey some order, they need some default order to obey in this case. We | ||||
| let R E T R E A T be this default order. | ||||
|                      ACM Transactions on Progranuning Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
| 388            L. Lamport, R. Shostak, and M. Pease | ||||
| 
 | ||||
|     We inductively define the Oral Message algorithms OM(m), for all nonnegative | ||||
| integers m, by which a c o m m a n d e r sends an order to n - 1 lieutenants. We show | ||||
| t h a t O M ( m ) solves the Byzantine Generals P r o b l e m for 3m + 1 or more generals | ||||
| in the presence of at most m traitors. We find it more convenient to describe this | ||||
| algorithm in terms of the lieutenants "obtaining a value" r a t h e r t h a n "obeying an | ||||
| order". | ||||
|     T h e algorithm assumes a function m a j o r i t y with the p r o p e r t y t h a t if a majority | ||||
| of the values vi equal v, then m a j o r i t y (Vl,.. •, v,-D equals v. (Actually, it assumes | ||||
| a sequence of such f u n c t i o n s - - o n e for each n.) T h e r e are two natural choices for | ||||
| the value of m a j o r i t y ( v 1 , . . . , v,-1): | ||||
| 1. T h e majority value a m o n g the vi if it exists, otherwise the value R E T R E A T ; | ||||
| 2. T h e m e d i a n of the vi, assuming t h a t t h e y come from an ordered set. | ||||
| T h e following algorithm requires only the aforementioned p r o p e r t y of m a j o r i t y . | ||||
|   Algorithm OM(0). | ||||
| (1) The commander sends his value to every lieutenant. | ||||
| (2) Each lieutenant uses the value he receives from the commander, or uses the value | ||||
|     RETREAT if he receives no value. | ||||
|   A l g o r i t h m O M ( m ) , m > O. | ||||
| (1) The commander sends his value to every lieutenant. | ||||
| (2) For each i, let vi be the value Lieutenant i receives from the commander, or else be | ||||
|     RETREAT if he re :eives no value. Lieutenant i acts as the commander in Algorithm | ||||
|     OM(m - 1) to send the value vi to each of the n - 2 other lieutenants. | ||||
| (3) For each i, and each j ~ i, let vj be the value Lieutenant i received from Lieutenant j | ||||
|     in step (2) (using Algorithm OM(m - 1)), or else RETREAT if he received no such | ||||
|     value. Lieutenant i uses the value majority (vl . . . . . v,-1 ). | ||||
|     T o u n d e r s t a n d how this algorithm works, we consider the case m = 1, n = 4. | ||||
| Figure 3 illustrates the messages received by L i e u t e n a n t 2 when the c o m m a n d e r | ||||
| sends the value v and L i e u t e n a n t 3 is a traitor. In the first step of OM(1), the | ||||
| c o m m a n d e r sends v to all three lieutenants. I n the second step, L i e u t e n a n t 1 | ||||
| sends the value v to L i e u t e n a n t 2, using the trivial algorithm OM(0). Also in the | ||||
| second step, the traitorous L i e u t e n a n t 3 sends L i e u t e n a n t 2 some other value x. | ||||
| In step 3, L i e u t e n a n t 2 t h e n has v~ = v2 = v and v3 = x, so he obtains the correct | ||||
| value v = m a j o r i t y ( v , v, x ) . | ||||
|     Next, we see w h a t h a p p e n s if the c o m m a n d e r is a traitor. Figure 4 shows the | ||||
| values received by the lieutenants if a traitorous c o m m a n d e r sends three arbitrary | ||||
| values x, y, and z to the three lieutenants. E a c h lieutenant obtains v~ = x, v2 = y, | ||||
| and v3 = z, so t h e y all obtain the same value m a j o r i t y ( x , y, z ) in step (3), | ||||
| regardless of w h e t h e r or not a n y of the three values x, y, and z are equal. | ||||
|      T h e recursive algorithm O M ( m ) invokes n - 1 separate executions of the | ||||
|  algorithm O M ( m - 1), each of which invokes n - 2 executions of OM(m - 2), etc. | ||||
|  This m e a n s that, for m > 1, a lieutenant sends m a n y separate messages to each | ||||
|  o t h e r lieutenant. T h e r e m u s t be some way to distinguish a m o n g these different | ||||
|  messages. T h e reader can verify t h a t all ambiguity is r e m o v e d if each lieutenant | ||||
|  i prefixes the n u m b e r i to the value vi t h a t he sends in step (2). As the recursion | ||||
|  "unfolds," the algorithm O M ( m - k) will be called (n - 1) . . . (n - k) times to | ||||
|  send a value prefixed by a sequence of k lieutenants' numbers. | ||||
|  ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
|     a~ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     c~ | ||||
|     p~ | ||||
| 
 | ||||
| 
 | ||||
|     ~JD | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     co O | ||||
|     .~'~ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|            Z~ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| / | ||||
|                 v~ | ||||
| 
 | ||||
|                 © | ||||
| 390             L. Lamport, R. Shostak, and M. Pease | ||||
| 
 | ||||
|     T o p r o v e the correctness of the algorithm OM{m) for a r b i t r a r y m, we first | ||||
| p r o v e the following l e m m a . | ||||
| 
 | ||||
|     LEMMA 1. F o r a n y m a n d k, A l g o r i t h m O M (m ) satisfies IC2 if there are more | ||||
| t h a n 2k + m g e n e r a l s a n d at m o s t k traitors. | ||||
| 
 | ||||
|     PROOF. T h e p r o o f is b y induction on m. IC2 only specifies w h a t m u s t h a p p e n | ||||
| if the c o m m a n d e r is loyal. Using A1, it is easy to see t h a t the trivial algorithm | ||||
| OM(0) works if the c o m m a n d e r is loyal, so the l e m m a is true for m = 0. We now | ||||
| a s s u m e it is true for m - 1, m > 0, a n d p r o v e it for m. | ||||
|     In step (1), the loyal c o m m a n d e r sends a value v to all n - 1 lieutenants. In | ||||
| step (2), e a c h loyal l i e u t e n a n t applies O M ( m - 1) with n - 1 generals. Since b y | ||||
| h y p o t h e s i s n > 2k + m, we h a v e n - 1 > 2k + (m - 1), so we can a p p l y the | ||||
| induction h y p o t h e s i s to conclude t h a t e v e r y loyal l i e u t e n a n t gets vj = v for e a c h | ||||
| loyal L i e u t e n a n t j. Since t h e r e are at m o s t k traitors, and n - 1 > 2k + (m - 1) | ||||
| _> 2k, a m a j o r i t y of the n - 1 lieutenants are loyal. Hence, e a c h loyal lieutenant | ||||
| h a s vi = v for a m a j o r i t y of the n - 1 values i, so he obtains majority(v1 . . . . , | ||||
| v,-1) = v in step (3), proving IC2. [] | ||||
| 
 | ||||
|   T h e following t h e o r e m asserts t h a t Algorithm O M ( m ) solves the B y z a n t i n e | ||||
| Generals Problem. | ||||
| 
 | ||||
|     THEOREM 1. F o r a n y m, A l g o r i t h m O M (m ) satisfies conditions IC1 a n d IC2 | ||||
| i f there are m o r e t h a n 3m g e n e r a l s a n d at m o s t m traitors. | ||||
| 
 | ||||
|     PROOF. T h e p r o o f is b y induction on m. I f t h e r e are no traitors, t h e n it is easy | ||||
| to see t h a t OM(0) satisfies IC1 and IC2. W e therefore a s s u m e t h a t the t h e o r e m | ||||
| is true for O M ( m - 1) a n d p r o v e it for O M ( m ) , m > 0. | ||||
|     W e first consider the case in which the c o m m a n d e r is loyal. B y taking k equal | ||||
| to m in L e m m a 1, we see t h a t O M ( m ) satisfies IC2. IC1 follows f r o m IC2 if the | ||||
| c o m m a n d e r is loyal, so we need only verify IC1 in the case t h a t the c o m m a n d e r | ||||
| is a traitor. | ||||
|     T h e r e are at m o s t m traitors, and the c o m m a n d e r is one of t h e m , so at m o s t | ||||
| m - 1 of the lieutenants are traitors. Since t h e r e are m o r e t h a n 3m generals, | ||||
| t h e r e are m o r e t h a n 3m - 1 lieutenants, and 3m - 1 > 3(m - 1). W e m a y | ||||
| therefore a p p l y the induction h y p o t h e s i s to conclude t h a t O M ( m - 1) satisfies | ||||
| conditions IC1 and IC2. Hence, f o r e a c h j, a n y two loyal lieutenants get the s a m e | ||||
| value for vj in step (3). (This follows f r o m IC2 if one of the two lieutenants is | ||||
| L i e u t e n a n t j, a n d f r o m IC1 Otherwise.) Hence, a n y two loyal lieutenants get the | ||||
| s a m e vector of values vl . . . . . Vn-~, and therefore obtain the s a m e value major- | ||||
| ity(vl . . . . . Vn-1) in step (3), proving IC1. [] | ||||
| 
 | ||||
| 4. A SOLUTION WITH SIGNED MESSAGES | ||||
| As we saw f r o m the scenario of Figures i and 2, it is the traitors' ability to lie t h a t | ||||
| m a k e s the B y z a n t i n e Generals P r o b l e m so difficult. T h e p r o b l e m b e c o m e s easier | ||||
| to solve if we can restrict t h a t ability. One w a y to do this is to allow the generals | ||||
| to send unforgeable signed messages. M o r e precisely, we add to A1-A3 the | ||||
| ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
|                                                          The Byzantine Generals Problem                             391 | ||||
| 
 | ||||
|      following assumption: | ||||
| 
 | ||||
|      A4 (a) A loyal general's signature cannot be forged, and any alteration of the | ||||
|             contents of his signed messages can be detected. | ||||
|         (b) Anyone can verify the authenticity of a general's signature. | ||||
| 
 | ||||
|           N o t e t h a t we make no assumptions about a traitorous general's signature. In | ||||
|      particular, we allow his signature to be forged by a n o t h e r traitor, t h e r e b y | ||||
|      permitting collusion among the traitors. | ||||
|          Now t h a t we have introduced signed messages, our previous argument t h a t | ||||
|      four generals are required to cope with one traitor no longer holds. In fact, a | ||||
|      three-general solution does exist. We now give an algorithm t h a t copes with m | ||||
|      traitors for any n u m b e r of generals. (The problem is vacuous if there are fewer | ||||
|      t h a n m + 2 generals.) | ||||
|          In our algorithm, the c o m m a n d e r sends a signed order to each of his lieutenants. | ||||
|      E a c h lieutenant t h e n adds his signature to t h a t order and sends it to the other | ||||
|      lieutenants, who add their signatures and send it to others, and so on. This means | ||||
|      t h a t a lieutenant must effectively receive one signed message, make several copies | ||||
|      of it, and sign and send those copies. It does not m a t t e r how these copies are | ||||
|      obtained; a single message might be photocopied, or else each message might | ||||
|      consist of a stack of identical messages which are signed and distributed as | ||||
|      required. | ||||
|          Our algorithm assumes a function choice which is applied to a set of orders to | ||||
|     /obtain a single one. T h e only requirements we make for this function are | ||||
| / | ||||
|     1. If the set V consists of the single element v, t h e n c h o i c e ( V ) = v. | ||||
|     2. choice(Q) = R E T R E A T , where O is the e m p t y set. | ||||
| 
 | ||||
|     N o t e t h a t one possible definition is to let c h o i c e ( V ) be the median element of | ||||
|      V--assuming t h a t there is an ordering of the elements. | ||||
|         In the following algorithm, we let x : i denote the value x signed by General i. | ||||
|     Thus, v :j: i denotes the value v signed by j, and t h e n t h a t value v : j signed by i. | ||||
|     We let General 0 be the commander. In this algorithm, each lieutenant i maintains | ||||
|     a set Vi, containng the set of properly signed orders he has received so far. (If the | ||||
|     c o m m a n d e r is loyal, t h e n this set should never contain more t h a n a single | ||||
|     element.) Do not confuse Vi, the set of o r d e r s he has received, with the set of | ||||
|     messages t h a t he has received. T h e r e m a y be m a n y different messages with the | ||||
|     same order. | ||||
| 
 | ||||
|       Algorithm S M (rn). | ||||
|     Initially Vi = 0. | ||||
|     (1) The commander signs and sends his value to every lieutenant. | ||||
|     (2) For each i: | ||||
|         (A) If Lieutenant i receives a message of the form v: 0 from the commander and he | ||||
|             has not yet received any order, then | ||||
|              (i) he lets V/equal (v); | ||||
|             (ii) he sends the message v: 0 : i to every other lieutenant. | ||||
|                             A C M Transactions on P r o g r a m m i n g Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
| 392       •    L. Lamport, R. Shostak, and M. Pease | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                                                "attack" | ||||
|                                                                  ~ | ||||
|                                                             :0 : 1 | ||||
|                                                                                    ':0 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                                                 "retreat"   :0 :2 | ||||
| 
 | ||||
|                           Fig. 5.   Algorithm SM(1); the c o m m a n d e r a traitor. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     (B) If Lieutenant i receives a message of the form v : 0 :jl : -.. : Jk and v is not in the set | ||||
|         Vi, then | ||||
|          (i) he adds v to Vi; | ||||
|         (ii) if k < m, then he sends the message v:0 :jl : - . . :jk : i to every lieutenant other | ||||
|              than jl . . . . . jk. | ||||
| (3) For each i: When Lieutenant i will receive no more messages, he obeys the order | ||||
|       choice( Vi). | ||||
| N o t e t h a t in step (2), L i e u t e n a n t i ignores a n y message containing an order v t h a t | ||||
| is already in the set Vi. | ||||
|      We have not specified how a lieutenant determines in step (3) t h a t he will | ||||
| receive no more messages. B y induction on k, one easily shows t h a t for each | ||||
| sequence of lieutenants j l , • • •, jk with k __ m, a lieutenant can receive at m o s t | ||||
| one message of the form v : 0 : j l : . . . :jk in step (2). If we require t h a t L i e u t e n a n t | ||||
| Jk either send such a message or else send a message reporting t h a t he will not | ||||
| send such a message, t h e n it is easy to decide w h e n all messages have been | ||||
| received. (By a s s u m p t i o n A3, a lieutenant can determine if a traitorous lieutenant | ||||
| jk sends neither of those two messages.) Alternatively, time-out can be used to | ||||
|  determine w h e n no more messages will arrive. T h e use of time-out is discussed in | ||||
|  Section 6. | ||||
|      N o t e t h a t in step (2), L i e u t e n a n t i ignores a n y messages t h a t do not have the | ||||
|  p r o p e r form of a value followed by a string of signatures. If packets of identical | ||||
|  messages are used to avoid having to copy messages, this m e a n s t h a t he throws | ||||
|  away a n y packet t h a t does n o t consist of a sufficient n u m b e r of identical, properly | ||||
|  signed messages. (There should be (n - k - 2)(n - k - 3) . . - (n - m - 2) copies | ||||
|  of the message if it has been signed by k lieutenants.) | ||||
|      Figure 5 illustrates Algorithm SM(1) for the case of three generals when the | ||||
|  c o m m a n d e r is a traitor. T h e c o m m a n d e r sends an " a t t a c k " order to one lieutenant | ||||
|  and a " r e t r e a t " order to the other. B o t h lieutenants receive the two orders in step | ||||
|  (2), so after step (2) V1 -- V2 ffi {"attack", "retreat"}, and t h e y both obey the | ||||
|  order choice{ {"attack", "retreat"} ). Observe t h a t here, unlike the situation in | ||||
|  Figure 2, the lieutenants know the c o m m a n d e r is a traitor because his signature | ||||
|  ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
|                                                             The Byzantine Generals Problem                     •     393 | ||||
| 
 | ||||
|  appears on two different orders, and A4 states t h a t only he could have generated | ||||
|  those signatures. | ||||
|    In Algorithm SM(m), a lieutenant signs his name to acknowledge his receipt of | ||||
|  an order. If he is the ruth lieutenant to add his signature to the order, then t h a t | ||||
|  signature is not relayed to anyone else by its recipient, so it is superfluous. (More | ||||
|  precisely, assumption A2 makes it unnecessary.) In particular, the lieutenants | ||||
|  need not sign their messages in SM(1). | ||||
|    We now prove the correctness of our algorithm. | ||||
|    THEOREM 2. For any m, Algorithm S M ( m ) solves the Byzantine Generals | ||||
|  Problem if there are at most m traitors. | ||||
|       PROOF. We first prove IC2. If the c o m m a n d e r is loyal, t h e n he sends his signed | ||||
|   order v: 0 to every lieutenant in step (1). E v e r y loyal lieutenant will therefore | ||||
|   receive the order v in step (2)(A). Moreover, since no traitorous lieutenant can | ||||
|   forge any other message of the form v' :0, a loyal lieutenant can receive no | ||||
|   additional order in step (2)(B). Hence, for each loyal L i e u t e n a n t i, the set Vi | ||||
|  obtained in step (2) consists of the single order v, which he will obey in step (3) | ||||
|  by p r o p e r t y 1 of the choice function. This proves IC2. | ||||
|      Since IC1 follows from IC2 if the c o m m a n d e r is loyal, to prove IC1 we need | ||||
|  only consider the case in which the c o m m a n d e r is a traitor. Two loyal lieutenants | ||||
|  i and j obey the same order in step (3) if the sets of orders Vi and Vj t h a t they | ||||
|  receive in step (2) are the same. Therefore, to prove IC1 it suffices to prove that, | ||||
|  if i puts an order v into Vi in step (2), t h e n j must put the same order v into V1 in | ||||
|  step (2). T o do this, we must show t h a t j receives a properly signed message | ||||
|  containing t h a t order. If i receives the order v in step (2)(A), t h e n he sends it to | ||||
| j in step (2)(A)(ii); s o j receives it (by A1). If i adds the order to Vi in step (2)(B), | ||||
|  t h e n he must receive a first message of the form v : 0 : j l : . . . : j~. I f j is one of the | ||||
| fl, t h e n by A4 he must already have received the order v. If not, we consider two | ||||
|  cases: | ||||
|    1. k < m. In this case, i sends the message v : 0 : j l : . . . :jk:i to j ; s o j must | ||||
| receive the order v. | ||||
|    2. k = m. Since the c o m m a n d e r is a traitor, at most m - 1 of the lieutenants | ||||
| are traitors. Hence, at least one of the lieutenants jl . . . . , jm is loyal. This loyal | ||||
| lieutenant must have sent j the value v when he first received it, so j must | ||||
| therefore receive t h a t value. | ||||
|    This completes the proof.                  [] | ||||
| 
 | ||||
| 5. MISSING C O M M U N I C A T I O N P A T H S | ||||
| T h u s far, we have assumed t h a t a general can send messages directly to every | ||||
| other general. We now remove this assumption. Instead, we suppose t h a t physical | ||||
| barriers place some restrictions on who can send messages to whom. We consider | ||||
| the generals to form the nodes of a simple, 2 finite undirected graph G, where an | ||||
| arc between two nodes indicates t h a t those two generals can send messages | ||||
| 
 | ||||
| 2 A s i m p l e g r a p h is one in which t h e r e is at m o s t one arc joining a n y two nodes, a nd every arc connects | ||||
| two d i s t i n c t nodes. | ||||
| 
 | ||||
|                               ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
| 394             L. Lamport, R. Shostak, and M. Pease | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|          f | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                                              J | ||||
|               Fig. 6.   A 3-regular graph.                     Fig. 7.   A graph that is not 3-regular. | ||||
| 
 | ||||
| 
 | ||||
| directly to one another. W e now extend Algorithms O M ( m ) and SM(m), which | ||||
| a s s u m e d G to be c o m p l e t e l y connected, to m o r e general graphs. | ||||
|     T o extend our oral message algorithm OM(m), we need the following definition, | ||||
| w h e r e two generals are said to be neighbors if t h e y are joined b y an arc. | ||||
|   Definition 1. | ||||
|       (a) A set of nodes (il, . . . , ip} is said to be a regular set of neighbors of a node | ||||
| /if | ||||
| (i) e a c h ij is a neighbor of i, and | ||||
| (ii) for a n y general k different f r o m i, there exist p a t h s yj,k f r o m ij to k not passing | ||||
|      t h r o u g h i such t h a t a n y two different p a t h s Yi,k h a v e no node in c o m m o n | ||||
|      o t h e r t h a n k. | ||||
|   (b) T h e g r a p h G is said to be p-regular if every node h a s a regular set of | ||||
| neighbors consisting o f p distinct nodes. | ||||
|     Figure 6 shows a n e x a m p l e of a simple 3-regular graph. Figure 7 shows an | ||||
| e x a m p l e of a g r a p h t h a t is not 3-regular because the central node h a s no regular | ||||
| set of neighbors containing t h r e e nodes. | ||||
|     W e extend O M ( m ) to an algorithm t h a t solves the Byzantine Generals P r o b l e m | ||||
| in the p r e s e n c e of rn traitors if the g r a p h G of generals is 3m-regular. (Note t h a t | ||||
| a 3 m - r e g u l a r g r a p h m u s t contain at least 3m + 1 nodes.} For allpositive integers | ||||
| m and p, we define the algorithm OM(m, p) as follows w h e n the g r a p h G of | ||||
| generals i s p - r e g u l a r . ( O M ( m , p ) is not defined if G is notp-regular.) T h e definition | ||||
| uses induction on m. | ||||
|       Algorithm OM (rn, p). | ||||
| (0) Choose a regular set N of neighbors of the commander consisting o f p lieutenants. | ||||
| (1) The commander sends his value to every lieutenant in N. | ||||
| (2) For each i in N, let vi be the value Lieutenant i receives from the commander, or else | ||||
|     R E T R E A T if he receives no value. Lieutenant i sends vi to every other lieutenant k as | ||||
|     follows: | ||||
|     (A) If m = 1, then by sending the value along the path yi,k whose existence is | ||||
|          guaranteed by part (a) (ii) of Definition 1. | ||||
|     (B) If rn > 1, then by acting as the commander in the algorithm OM(m - 1, p - 1), | ||||
|          with the graph of generals obtained by removing the original commander from G. | ||||
| ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
|                                                  The Byzantine Generals Problem               395 | ||||
| 
 | ||||
|  (3) For each k, and each i in N with i ~ k, let vi be the value Lieutenant k received from | ||||
|      Lieutenant i in step (2), or RETREAT if he received no value. Lieutenant k uses the | ||||
|      value majority(vi . . . . . . vi,), where N = {il. . . . . ip}. | ||||
|   Note t h a t removing a single node from a p-regular graph leaves a (p - 1)- | ||||
| regular graph. Hence, one can apply the algorithm OM(m - 1, p - 1) in step | ||||
| (2)(B). | ||||
|   We now prove t h a t OM(m, 3m) solves the Byzantine Generals Problem if there | ||||
| are at most m traitors. T h e proof is similar to the proof for the algorithm OM(m) | ||||
| and will just be sketched. It begins with the following extension of L e m m a 1. | ||||
|   LEMMA 2. F o r any m > 0 a n d a n y p >_ 2k + m, A l g o r i t h m O M (m, p) satisfies | ||||
| IC2 i f there are at m o s t k traitors. | ||||
| 
 | ||||
|      PROOF. For m -- 1, observe t h a t a lieutenant obtains the value majority(v1, | ||||
| . . . , vp), where each vi is a value sent to him by the c o m m a n d e r along a p a t h | ||||
| disjoint from the p a t h used to send the other values to him. Since there are at | ||||
| most k traitors and p __ 2k + 1, more t h a n half of those paths are composed | ||||
| entirely of loyal lieutenants. Hence, if the c o m m a n d e r is loyal, t h e n a majority of | ||||
| the values vi will equal the value he sent, which implies that IC2 is satisfied. | ||||
|      Now assume the l e m m a for m - 1, m > 1. If the c o m m a n d e r is loyal, t h e n each | ||||
| of the p lieutenants in N gets the correct value. Since p > 2k, a majority of t h e m | ||||
| are loyal, and by the induction hypothesis each of t h e m sends the correct value | ||||
| to every loyal lieutenant. Hence, each loyal lieutenant gets a majority of correct | ||||
| values, t h e r e b y obtaining the correct value in step (3). [] | ||||
| 
 | ||||
|   T h e correctness of Algorithm OM(m, 3m) is an immediate consequence of the | ||||
| following result. | ||||
|    THEOREM 3. F o r a n y m > 0 a n d a n y p >_ 3m, A l g o r i t h m O M ( m , p) solves the | ||||
| B y z a n t i n e Generals P r o b l e m i f there are at m o s t m traitors. | ||||
| 
 | ||||
|     PROOF. B y L e m m a 2, letting k = m, we see t h a t OM(m, p ) satisfies IC2. If the | ||||
| c o m m a n d e r is loyal, t h e n IC1 follows from IC2, so we need only prove IC1 under | ||||
| the assumption t h a t the c o m m a n d e r is a traitor. T o do this, we prove t h a t every | ||||
| loyal lieutenant gets the same set of values vi in step (3). If m = 1, t h e n this | ||||
| follows because all the lieutenants, including those in N, are loyal and the paths | ||||
| ~/i,k do not pass through the commander. For m > 1, a simple induction argument | ||||
| can be applied, s i n c e p _ 3m implies t h a t p - 1 _ 3(m - 1). [] | ||||
|    Our extension of Algorithm OM(m) requires t h a t the graph G be 3m-regular, | ||||
| which is a r a t h e r strong connectivity hypothesis. 3 In fact, if there are only 3m + | ||||
| 1 generals (the m i n i m u m n u m b e r required), t h e n 3m-regularity means complete | ||||
| connectivity, and Algorithm OM(m, 3m) reduces to Algorithm OM(m). In con- | ||||
| trast, Algorithm SM(m) is easily extended to allow the weakest possible connec- | ||||
| tivity hypothesis. Let us first consider how m u c h connectivity is needed for the | ||||
| Byzantine Generals Problem to be solvable. IC2 requires t h a t a loyal lieutenant | ||||
| obey a loyal commander. This is clearly impossible if the c o m m a n d e r cannot | ||||
| communicate with the lieutenant. In particular, if every message from the | ||||
| 
 | ||||
| 3A recent algorithm of Dolev [2] requires less connectivity. | ||||
|                          ACMTransactionson ProgrammingLanguagesand Systems,Vol.4, No. 3, July 1982. | ||||
| 396            L. Lamport, R. Shostak, and M. Pease | ||||
| 
 | ||||
| 
 | ||||
| commander to the lieutenant must be relayed by traitors, then there is no way to | ||||
| guarantee that the lieutenant gets the commander's order. Similarly, IC1 cannot | ||||
| be guaranteed if there are two lieutenants who can only communicate with one | ||||
| another via traitorous intermediaries. | ||||
|   Th e weakest connectivity hypothesis for which the Byzantine Generals Prob- | ||||
| lem is solvable is that the subgraph formed by the loyal generals be connected. | ||||
| We show that under this hypothesis, the algorithm SM(n - 2) is a solution, where | ||||
| n is the number of generals--regardless of the number of traitors. Of course, we | ||||
| must modify the algorithm so that generals only send messages to where they | ||||
| can be sent. More precisely, in step (1), the commander sends his signed order | ||||
| only to his neighboring lieutenants; and in step (2)(B), Lieutenant i only sends | ||||
| the message to every neighboring lieutenant not among the jr. | ||||
|   We prove the following more general result, where the diameter of a graph is | ||||
| the smallest number d such that any two nodes are connected by a path | ||||
| containing at most d arcs. | ||||
|   THEOREM 4. For any m and d, if there are at most m traitors and the | ||||
| subgraph of loyal generals has diameter d, then Algorithm S M ( m + d - 1) (with | ||||
| the above modification) solves the Byzantine Generals Problem. | ||||
|   PROOF. The proof is quite similar to that of T h e o r e m 2 and is just sketched | ||||
| here. To prove IC2, observe that by hypothesis there is a path from the loyal | ||||
| commander to a lieutenant i going through d - 1 or fewer loyal lieutenants. | ||||
| Those lieutenants will correctly relay the order until it reaches i. As before, | ||||
| assumption A4 prevents a traitor from forging a different order. | ||||
|   To prove IC1, we assume the commander is a traitor and must show that any | ||||
| order received by a loyal lieutenant i is also received by a loyal lieutenant j. | ||||
| Suppose i receives an order v : 0 :j~ : . . - :jk not signed by j. If k < m, then i will | ||||
| send it to every neighbor who has not already received that order, and it will be | ||||
| relayed t o j within d - 1 more steps. If k _> m, then one of the first m signers must | ||||
| be loyal and must have sent it to all of his neighbors, whereupon it will be relayed | ||||
| by loyal generals and will reach j within d - 1 steps. [] | ||||
|  COROLLARY. If the graph of loyal generals is connected, then SM(n - 2) (as | ||||
| modified above) solves the Byzantine Generals Problem for n generals. | ||||
|   PROOF. Let d be the diameter of the graph of loyal generals. Since the diameter | ||||
| of a connected graph is less than the number of nodes, there must be more than | ||||
| d loyal generals and fewer than n - d traitors. T he result follows from the | ||||
| theorem by letting m = n - d - 1. [] | ||||
|    T h e o r e m 4 assumes that the subgraph of loyal generals is connected. Its proof | ||||
| is easily extended to show that even if this is not the case, if there are at most m | ||||
| traitors, then the algorithm SM(m + d - 1) has the following two properties: | ||||
| 1. Any two loyal generals connected by a path of length at most d passing | ||||
|    through only loyal generals will obey the same order. | ||||
| 2. If the commander is loyal, then any loyal lieutenant connected to him by a | ||||
|    path of length at most m + d passing only through loyal generals will obey his | ||||
|    order. | ||||
|  ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
|                                               The Byzantine Generals Problem               •    397 | ||||
| 
 | ||||
| 6. RELIABLE S Y S T E M S | ||||
| Other than using intrinsically reliable circuit components, the only way we know | ||||
| to implement a reliable computer system is to use several different "processors" | ||||
| to compute the same result, and then to perform a majority vote on their outputs | ||||
| to obtain a single value. (The voting may be performed within the system, or | ||||
| externally by the users of the output.) This is true whether one is implementing | ||||
| a reliable computer using redundant circuitry to protect against the failure of | ||||
| individual chips, or a ballistic missile defense system using redundant computing | ||||
| sites to protect against the destruction of individual sites by a nuclear attack. | ||||
| The only difference is in the size of the replicated "processor". | ||||
|    The use of majority voting to achieve reliability is based upon the assumption | ||||
| that all the nonfaulty processors will produce the same output. This is true so | ||||
| long as they all use the same input. However, any single input datum comes from | ||||
| a single physical component--for example, from some other circuit in the reliable | ||||
| computer, or from some radar site in the missile defense system--and a malfunc- | ||||
| tioning component can give different values to different processors. Moreover, | ||||
| different processors can get different values even from a nonfaulty input unit if | ||||
| they read the value while it is changing. For example, if two processors read a | ||||
| clock while it is advancing, then one may get the old time and the other the new | ||||
| time. This can only be prevented by synchronizing the reads with the advancing | ||||
| of the clock. | ||||
|    In order for majority voting to yield a reliable system, the following two | ||||
| conditions should be satisfied: | ||||
| 1. All nonfaulty processors must use the same input value (so they produce the | ||||
|    same output). | ||||
| 2. If the input unit is nonfaulty, then all nonfaulty processes use the value it | ||||
|    provides as input (so they produce the correct output). | ||||
| These are just our interactive consistency conditions IC1 and IC2, where the | ||||
| "commander" is the unit generating the input, the "lieutenants" are the proces- | ||||
| sors, and "loyal" means nonfaulty. | ||||
|    It is tempting to try to circumvent the problem with a "hardware" solution. | ||||
| For example, one might try to insure that all processors obtain the same input | ||||
| value by having them all read it from the same wire. However, a faulty input unit | ||||
| could send a marginal signal along the wire--a signal that can be interpreted by | ||||
| some processors as a 0 and by others as a 1. There is no way to guarantee that | ||||
| different processors will get the same value from a possibly faulty input device | ||||
| except by having the processors communicate among themselves to solve the | ||||
| Byzantine Generals Problem. | ||||
|   Of course, a faulty input device may provide meaningless input values. All that | ||||
| a Byzantine Generals solution can do is guarantee that all processors use the | ||||
| same input value. If the input is an important one, then there should be several | ||||
| separate input devices providing redundant values. For example, there should be | ||||
| redundant radars as well as redundant processing sites in a missile defense | ||||
| system. However, redundant inputs cannot achieve reliability; it is still necessary | ||||
| to insure that the nonfaulty processors use the redundant data to produce the | ||||
| same output. | ||||
|                      ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
| 398             L. Lamport, R. Shostak, and M. Pease | ||||
| 
 | ||||
|    In case the input device is nonfaulty but gives different values because it is | ||||
| read while its value is changing, we still want the nonfaulty processors to obtain | ||||
| a reasonable input value. It can be shown that, if the functions majority and | ||||
| choice are taken to be the median functions, then our algorithms have the | ||||
| property that the value obtained by the nonfaulty processors lies within the range | ||||
| of values provided by the input unit. Thus, the nonfaulty processors will obtain | ||||
| a reasonable value so long as the input unit produces a reasonable range of values. | ||||
|    We have given several solutions, but they have been stated in terms of | ||||
| Byzantine generals rather than in terms of computing systems. We now examine | ||||
| how these solutions can be applied to reliable computing systems. Of course, | ||||
| there is no problem implementing a "general's" algorithm with a processor. T he | ||||
| problems lie in implementing a message passing system that meets assumptions | ||||
| A1-A3 (assumptions A1-A4 for Algorithm SM(m)). We now consider these | ||||
| assumptions in order. | ||||
|    A1. Assumption A1 states that every message sent by a nonfaulty processor is | ||||
| delivered correctly. In real systems, communication lines can fail. For the oral | ||||
| message algorithms OM(m) and OM(m, p), the failure of the communication line | ||||
| joining two processors is indistinguishable from the failure of one of the proces- | ||||
| sors. Hence, we can only guarantee that these algorithms will work in the presence | ||||
| of up to m failures, be they processor or communication line failures. (Of course, | ||||
| the failure of several communication lines attached to the same processor is | ||||
| equivalent to a single processor failure.) If we assume that a failed communication | ||||
| line cannot result in the forgery of a signed message--an assumption which we | ||||
| will see below is quite reasonable, then our signed message algorithm SM(m) is | ||||
| insensitive to communication line failure. More precisely, T heorem 4 remains | ||||
| valid even with communication line failure. A failed communication line has the | ||||
| same effect as simply removing the communication line--it lowers the connectiv- | ||||
| ity of the processor graph. | ||||
|    A2. Assumption A2 states that a processor can determine the originator of any | ||||
| message that it received. What is actually necessary is that a faulty processor not | ||||
| be able to impersonate a nonfaulty one. In practice, this means that interprocess | ||||
| communication be over fixed lines rather than through some message switching | ||||
| network. (If a switching network is used, then faulty network nodes must be | ||||
| considered, and the Byzantine Generals Problem appears again.) Note that | ||||
| assumption A2 is not needed if A4 is assumed and all messages are signed, since | ||||
| impersonation of another processor would imply forging its messages. | ||||
|    A3. Assumption A3 requires that the absence of a message can be detected. | ||||
| T h e absence of a message can only be detected by its failure to arrive within | ||||
| some fixed length of t i m e - - i n other words, by the use of some time-out conven- | ||||
| tion. Th e use of time-out to satisfy A3 requires two assumptions: | ||||
| 1. Th er e is a fixed maximum time needed for the generation and transmission of | ||||
|    a message. | ||||
| 2. Th e sender and receiver have clocks that are synchronized to within some | ||||
|    fixed maximum error. | ||||
| T h e need for the first assumption is fairly obvious, since the receiver must know | ||||
| ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
|                                               The Byzantine Generals Problem                     399 | ||||
| 
 | ||||
| how long he needs to wait for the message to arrive. (The generation time is how | ||||
| long it takes the processor to send the message after receiving all the input | ||||
| necessary to generate it.) T he need for the second assumption is less obvious. | ||||
| However, it can be shown that either this assumption or an equivalent one is | ||||
| necessary to solve the Byzantine Generals Problem. More precisely, suppose that | ||||
| we allow algorithms in which the generals take action only in the following | ||||
| circumstances: | ||||
| 
 | ||||
| 1. At some fixed initial time (the same for all generals). | ||||
| 2. Upon the receipt of a message. | ||||
| 3. When a randomly chosen length of time has elapsed. (I.e., a general can set a | ||||
|    timer to a random value and act when the timer goes off.) | ||||
| 
 | ||||
|   {This yields the most general class of algorithms we can envision which does not | ||||
|  allow the construction of synchronized clocks.) It can be shown that no such | ||||
|  algorithm can solve the Byzantine Generals Problem if messages can be trans- | ||||
|  mitted arbitrarily quickly, even if there is an upper bound on message transmis- | ||||
|  sion delay. Moreover, no solution is possible even if we restrict the traitors so | ||||
|  that the only incorrect behavior they are permitted is the failure to send a | ||||
|  message. T h e proof of this result is beyond the scope of this pa, Jer. Note that | ||||
|  placing a lower as well as an upper bound on transmission delay ahows processors | ||||
|  to implement clocks by sending messages back and forth. | ||||
|     Th e above two assumptions make it easy to detect unsent messages. Let/z be | ||||
|  the maximum message generation and transmission delay, and assume the | ||||
| nonfaulty processors have clocks that differ from one another by at most T at any | ||||
| time. T h e n any message that a nonfaulty process should begin to generate by | ||||
| time T on its clock will arrive at its destination by time T + # + T on the receiver's | ||||
| clock. Hence, if the receiver has not received the message by that time, then it | ||||
| may assume that it was not sent. (If it arrives later, then the sender must be | ||||
| faulty, so the correctness of our algorithms does not depend upon the message | ||||
| being sent.) By fLxing the time at which the input processor sends its value, one | ||||
| can calculate until what time on its own clock a processor must wait for each | ||||
| message. For example, in Algorithm SM(m) a processor must wait until time To | ||||
| + k(# + ~) for any message having k signatures, where To is the time (on his | ||||
| clock) at which the commander starts executing the algorithm. | ||||
|    No two clocks run at precisely the same rate, so no matter how accurately the | ||||
| processors' clocks are synchronized initially, they will eventually drift arbitrarily | ||||
| far apart unless they are periodically resynchronlzed. We therefore have the | ||||
| problem of keeping the processors' clocks all synchronized to within some fixed | ||||
| amount, even if some of the processors are faulty. This is as difficult a problem | ||||
| as the Byzantine Generals Problem itself. Solutions to the clock synchroniza'~ion | ||||
| problem exist which are closely related to our Byzantine Generals solutions. T h e y | ||||
| will be described in a future paper. | ||||
|    A4. Assumption A4 requires that processors be able to sign their messages in | ||||
| such a way that a nonfaulty processor's signature cannot be forged. A signature | ||||
| is a piece of redundant information Si(M) generated by process i from a data | ||||
| item M. A message signed by i consists of a pair (M, Si(M)). To meet parts (a) | ||||
|                      ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
| 400            L. Lamport, R. Shostak, and M. Pease | ||||
| 
 | ||||
| and (b) of A4, the function Si must have the following two properties: | ||||
| 
 | ||||
| (a) If processor i is nonfaulty, then no faulty processor can generate Si(M). | ||||
| (b) Given M and X, any process can determine i f X equals Si(M). | ||||
| 
 | ||||
|    Property (a) can never be guaranteed, since Si(M) is just a data item, and a | ||||
| faulty processor could generate any data item. However, we can make the | ||||
| probability of its violation as small as we wish, thereby making the system as | ||||
| reliable as we wish. How this is done depends upon the type of faults we expect | ||||
| to encounter. There are two cases of interest: | ||||
| 
 | ||||
|    1. Random Malfunction. By making Si a suitably "randomizing" function, we | ||||
| can make the probability that a random malfunction in a processor generates a | ||||
| correct signature essentially equal to the probability of its doing so through a | ||||
| random choice procedure--that is, the reciprocal of the number of possible | ||||
| signatures. The following is one method for doing this. Assume that messages are | ||||
| encoded as positive integers less than P, where P is a power of two. Let Si(M) | ||||
| equal M * Ki mod P, where Ki is a randomly chosen odd number less than P. | ||||
| Letting K [ 1 be the unique number less than P such that Ki * K i 1 - 1 mod P, a | ||||
| process can check that X = Si (M) by testing that M = X * K~ 1 mod P. If another | ||||
| processor does not have Ki in its memory, then the probability of its generating | ||||
| the correct signature M * Ki for a single (nonzero) message M should be l/P: its | ||||
| probability of doing so by random choice. (Note that if the processor could obtain | ||||
| Ki by some simple procedure, then there might be a larger probability of a faulty | ||||
| processor j forging i's signature by substituting Ki for K/when trying to compute | ||||
| Sj(M).) | ||||
|    2. Malicious Intelligence. If the faulty processor is being guided by a malicious | ||||
| intelligence--for example, if it is a perfectly good processor being operated by a | ||||
| human who is trying to disrupt the system--then the construction of the signature | ||||
| function Si becomes a cryptography problem. We refer the reader to [1] and [4] | ||||
| for a discussion of how this problem can be solved. | ||||
| 
 | ||||
|   Note that it is easy to generate the signature Si (M) if the process has already | ||||
| seen that signature. Hence, it is important that the same message never have to | ||||
| be signed twice. This means that, when using SM(m) repeatedly to distribute a | ||||
| sequence of values, sequence numbers should be appended to the values to | ||||
| guarantee uniqueness. | ||||
| 
 | ||||
| 7. CONCLUSION | ||||
| We have presented several solutions to the Byzantine Generals Problem, under | ||||
| various hypotheses, and shown how they can be used in implementing reliable | ||||
| computer systems. These solutions are expensive in both the amount of time and | ||||
| the number of messages required. Algorithms OM(m) and SM(m) both require | ||||
| message paths of length up to m 4- 1. In other words, each lieutenant may have | ||||
| to wait for messages that originated at the commander and were then relayed via | ||||
| m other lieutenants. Fischer and Lynch have shown that this must be true for | ||||
| any solution that can cope with m traitors, so our solutions are optimal in that | ||||
| respect. Our algorithms for a graph that is not completely connected require | ||||
| ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
|                                                 The Byzantine Generals Problem                     401 | ||||
| 
 | ||||
| message paths of length up to rn + d, where d is the diameter of the subgraph of | ||||
| loyal generals. We suspect that this is also optimal. | ||||
|   Algorithms OM(m) and SM(m) involve sending up to (n - 1)(n - 2) . . . | ||||
| (n - m - 1) messages. The number of separate messages required can certainly | ||||
| be reduced by combining messages. It may also be possible to reduce the amount | ||||
| of information transferred, but this has not been studied in detail. However, we | ||||
| expect that a large number of messages will still be required. | ||||
|   Achieving reliability in the face of arbitrary malfunctioning is a difficult | ||||
| problem, and its solution seems to be inherently expensive. The only way to | ||||
| reduce the cost is to make assumptions about the type of failure that may occur. | ||||
| For example, it is often assumed that a computer may fail to respond but will | ||||
| never respond incorrectly. However, when extremely high reliability is required, | ||||
| such assumptions cannot be made, and the full expense of a Byzantine Generals | ||||
| solution is required. | ||||
| 
 | ||||
| REFERENCES | ||||
|  1. DIFFIE, W., AND HELLMAN, M.E. New directions in cryptography. IEEE Trans. Inf. Theory | ||||
|     IT-22 (Nov. 1976), 644-654. | ||||
|  2. DOLEV, D. The Byzantine generals strike again. J. Algorithms 3, 1 (Jan. 1982). | ||||
|  3. PEASE, M., SHOSTAK, R., AND LAMPORT, L. Reaching agreement in the presence of faults. J. | ||||
|     ACM 27, 2 (Apr. 1980), 228-234. | ||||
|  4. RIVEST, R.L., SHAMIR, A., AND ADLEMAN, L. A method for obtaining digital signatures and | ||||
|     public-key cryptosystems. Cornrnun. ACM 21, 2 (Feb. 1978), 120-126. | ||||
| 
 | ||||
| 
 | ||||
| Received April 1980; revised November 1981; accepted November 1981 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                        ACM Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982. | ||||
|  | ||||
							
								
								
									
										99
									
								
								bft/generals.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								bft/generals.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| // This time writing in C because c++ gives me agita
 | ||||
| 
 | ||||
| #include "stdio.h" | ||||
| #include "stdlib.h" | ||||
| 
 | ||||
| 
 | ||||
| #define HOLD 0 | ||||
| #define ATTACK 1 | ||||
| #define RETREAT 2 | ||||
| 
 | ||||
| #define g_idx(idx) (idx * sizeof(struct General)) | ||||
| struct General { | ||||
| 	int id; | ||||
| 	int plan; | ||||
| 	int check; | ||||
| 	// two neighbors max because why tf not
 | ||||
| 	struct General* neighbor_a; | ||||
| 	struct General* neighbor_b; | ||||
| }; | ||||
| 
 | ||||
| void general_init(struct General* g, int id) { | ||||
| 	g->id = id; | ||||
| 	g->plan = rand() % 3; | ||||
| 	g->neighbor_a = NULL; | ||||
| 	g->neighbor_b = NULL; | ||||
| 	g->check = 0; | ||||
| } | ||||
| 
 | ||||
| void general_connect_neighbors(struct General* a, struct General* b) { | ||||
| 	// aa
 | ||||
| 	if(a->neighbor_a == NULL && b->neighbor_a == NULL) { | ||||
| 		a->neighbor_a = b; | ||||
| 		b->neighbor_a = a; | ||||
| 	} | ||||
| 	// bb
 | ||||
| 	else if(a->neighbor_b == NULL && b->neighbor_b == NULL) { | ||||
| 		a->neighbor_b = b; | ||||
| 		b->neighbor_b = a; | ||||
| 	} | ||||
| 	// ab
 | ||||
| 	else if(a->neighbor_a == NULL && b->neighbor_b == NULL) { | ||||
| 		a->neighbor_a = b; | ||||
| 		b->neighbor_b = a; | ||||
| 	} | ||||
| 	// ba
 | ||||
| 	else { | ||||
| 		a->neighbor_b = b; | ||||
| 		b->neighbor_a = a; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void generals_assign_neighbors(int id_g, struct General[] generals, int pool_size) { | ||||
| 	// make sure we don't pick ourselves by acdident
 | ||||
| 	int a = rand() % pool_size; | ||||
| 	int b = rand() % pool_size; | ||||
| 
 | ||||
| 	// make sure we don't pick ourselves ever
 | ||||
| 	while(a == id_g) {a = rand() % pool_size;} | ||||
| 	while(b == id_g && b == a) {b = rand() % pool_size;} | ||||
| 
 | ||||
| 	general_connect_neighbors(generals[id_g], &generals[a], &generals[b]); | ||||
| } | ||||
| 
 | ||||
| void generals_vote_rr(struct General* generals, int pool_size) { | ||||
| 	// Each general must now tell the other generals what their plan actually is
 | ||||
| 	// We keep track of this by a value flag in the generals struct `check`
 | ||||
| 	for(int i = 0; i < pool_size; i++) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void general_reveal_info(const struct General* g) { | ||||
| 	char* plans[3] = {"Hold", "Attack", "Retreat"}; | ||||
| 	printf("ID: %d\tPlan%s\tNeighbors: %d  &%d\n",  | ||||
| 			g->id, plans[g->plan],g->neighbor_a->id, g->neighbor_b->id); | ||||
| } | ||||
| 
 | ||||
| int main(void) { | ||||
| 	const int general_count = 5; | ||||
| 	struct General generals[general_count]; | ||||
| 
 | ||||
| 	// connect the commander to two of the generals
 | ||||
| 	for(int i = 0; i < general_count; i++) { | ||||
| 		general_init(&generals[i], i); | ||||
| 		// pick two random generals that aren't us to befriend
 | ||||
| 		generals_assign_neighbors(i, generals, general_count); | ||||
| 	} | ||||
| 
 | ||||
| 	// Show off each generals starting state
 | ||||
| 	for(int i = 0; i<general_count;i++) { | ||||
| 		general_reveal_info(&generals[i]); | ||||
| 	} | ||||
| 
 | ||||
| 	// For `n` Byzantine generals and `m` Albanian generals
 | ||||
| 	// We demonstrate the "three-general" solution
 | ||||
| 	// This solution implies that 3 Byzantine generals can handle 1 traitor
 | ||||
| 
 | ||||
| 	// First the byzantine commander simulates
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										82
									
								
								blockchain.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								blockchain.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | ||||
| #include <tgmath.h> | ||||
| #include <cstring> | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| constexpr void compute_md5_table(uint32_t*, size_t); | ||||
| 
 | ||||
| class Block { | ||||
| public: | ||||
| 	char* data; | ||||
| 	char* hash; | ||||
| 	char* previous_hash; | ||||
| 
 | ||||
| 	Block(char*, char*); | ||||
| 	char* hmac(char*); | ||||
| }; | ||||
| 
 | ||||
| Block::Block(char* data, char* prev) { | ||||
| 	this->data = data; | ||||
| 	this->hash = this->hmac(data); | ||||
| 	this->previous_hash = prev; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| char* Block::hmac(char* input) { | ||||
| 	const size_t _TABLE_SIZE = 64; | ||||
| 	uint32_t table[_TABLE_SIZE]; | ||||
| 	compute_md5_table(table, _TABLE_SIZE); | ||||
| 
 | ||||
| 	// values are taken straight from wikipedia
 | ||||
| 	size_t a0 = 0x67452301;   // A
 | ||||
| 	size_t b0 = 0xefcdab89;   // B
 | ||||
| 	size_t c0 = 0x98badcfe;   // C
 | ||||
| 	size_t d0 = 0x10325476;   // D
 | ||||
| 
 | ||||
| 	// lots of reallocs  inc
 | ||||
| 	size_t msg_len = strlen(input) + 1; | ||||
| 	uint8_t* buf = (uint8_t*)malloc(msg_len /* for the '1' bit */); | ||||
| 	memcpy(buf, input, msg_len); | ||||
| 	buf[strlen(input)] = 0x80; // adding in the '1' bit along with 7 bits for padding
 | ||||
| 
 | ||||
| 	// calculate length of final message content with all padding
 | ||||
| 	size_t message_len_bits = msg_len * 8; | ||||
| 	while((message_len_bits) % 512 != 64 ) { | ||||
| 		message_len_bits += 8; | ||||
| 	} | ||||
| 
 | ||||
| 	// prepare out new hash buffer which has a mutaable state
 | ||||
| 	uint8_t* hash_buf = (uint8_t*)malloc(message_len_bits / 8); | ||||
| 	memcpy(hash_buf, buf, msg_len); | ||||
| 
 | ||||
| 	size_t hunk_count = msg_len/8; | ||||
| 	for(size_t i =0; i < hunk_count; i+=8) { | ||||
| 		uint8_t* hunk = &hash_buf[i]; // length should always be 8(bytes)/512 bits
 | ||||
| 		// split the hunk into pieces
 | ||||
| 		uint32_t parts[16]; | ||||
| 		for(size_t p = 0; p < 16; p+=32) { | ||||
| 			parts[p] = (uint32_t)hunk[p]; | ||||
| 		} | ||||
| 		for(size_t z = 0;z<16;z++) { | ||||
| 			printf("%08X ", parts[z]); | ||||
| 		} | ||||
| 		printf("\n"); | ||||
| 
 | ||||
| 	} | ||||
| 	free(hash_buf); | ||||
| 	free(buf); | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| int main(void) { | ||||
| 	Block* b = new Block("something", NULL); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| constexpr void compute_md5_table(uint32_t* table, size_t size) { | ||||
| 	for(int i = 0; i < 64; i++) { | ||||
| 		table[i] = floor( pow(2,32) * abs( sin(i+1) ) ); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										14
									
								
								concptual.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								concptual.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| # Ledger | ||||
| 
 | ||||
| * Receives updates from clients | ||||
| * Periodically updates other ledgers of the longest chain it has | ||||
| 
 | ||||
| # Client | ||||
| 
 | ||||
| * Does work and submits that work to a ledger | ||||
| * Can be rewarded from a ledger with reports that let clients know of their rewards | ||||
| 
 | ||||
| 
 | ||||
| # Client Updates & Mining | ||||
| 
 | ||||
| Wee need some way of proving that a client has mined a new block or chain of blocks | ||||
							
								
								
									
										12
									
								
								socket/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								socket/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| all: setup client-server | ||||
| 
 | ||||
| setup: | ||||
| 	mkdir -p bin/ | ||||
| 
 | ||||
| client-server:  | ||||
| 	g++ transaction.cc client.cc -o bin/client | ||||
| 	g++ transaction.cc client.cc -o bin/server | ||||
| 
 | ||||
| clean: | ||||
| 	rm -f bin/server | ||||
| 	rm -f bin/client | ||||
							
								
								
									
										37
									
								
								socket/client.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								socket/client.cc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| // Sample of a client which sends up preconstructed data to our server
 | ||||
| #include <iostream> | ||||
| #include <stdlib.h> | ||||
| #include <sys/socket.h> | ||||
| #include <arpa/inet.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include "transaction.h" | ||||
| 
 | ||||
| #define PORT 6969 | ||||
| 
 | ||||
| int main(void) { | ||||
|     sockaddr_in server_addr; | ||||
|     Transaction sample_ta; | ||||
|     int sock = socket(AF_INET, SOCK_STREAM, 0); | ||||
|     if(sock < 0) { | ||||
|         std::cerr << "Could not create socket\n"; | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     server_addr.sin_family = AF_INET; | ||||
|     server_addr.sin_port = PORT; | ||||
|     if(inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) { | ||||
|         std::cerr << "Invalid address\n"; | ||||
|         return 1; | ||||
|     } | ||||
|     if(connect(sock, (sockaddr*)&server_addr, sizeof(server_addr)) < 0) { | ||||
|         std::cerr << "Conection failed\n"; | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     send(sock, &sample_ta, sizeof(Transaction), 0); | ||||
|     char buffer[1024] = {0}; | ||||
|     int response = read(sock, buffer, 1024); | ||||
|     std::cout << "BEGIN BUFFER\n" << buffer << "\nEND BUFFER\n"; | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										13
									
								
								socket/server.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								socket/server.cc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| // sample server which merely parses out transactions
 | ||||
| #include <iostream> | ||||
| #include <stdlib.h> | ||||
| #include <sys/socket.h> | ||||
| #include <arpa/inet.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include "transaction.h" | ||||
| 
 | ||||
| 
 | ||||
| int main(void) { | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										7
									
								
								socket/transaction.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								socket/transaction.cc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| #include "transaction.h" | ||||
| 
 | ||||
| Transaction::Transaction(void) { | ||||
|     this->magic = MAGIC; | ||||
|     this->meta = 0; | ||||
|     this->amount = 0; | ||||
| } | ||||
							
								
								
									
										9
									
								
								socket/transaction.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								socket/transaction.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| #include <stdint.h> | ||||
| #define MAGIC 0x54314E59 // T1NY in hex btw
 | ||||
| 
 | ||||
| struct Transaction { | ||||
|     uint32_t magic; | ||||
|     uint16_t meta; | ||||
|     uint64_t amount; | ||||
|     Transaction(void); | ||||
| }; | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user