- Apr 2024
-
-
If one user marks a word as bold and another user marks the same word as non-bold, thereis no final state that preserves both users’ intentions and also ensures convergence
Having "bold" mean some semantics, e.g., important.
Then they merge. Alice does not consider it important, Bob does -> render both. E.g., Bob's "importance" expressed as bold, Alices "not important" as grayed text.
-
If the context has changed
E.g.,
"Ny is a great city."
Alice removes "great".
Bob wonts to replace it with "gorgeous", by removing "reat" and adding "orgeous".
Having merged:
"Ny is a orgeous city."
Begs for semantic intent preservation, such as "reword great to gorgeous".
-
Rather than seeing document history as a linear sequence of versions,we could see it as a multitude of projected views on top of a database of granular changes
That would be nice.
As well as preserving where ops come from.
Screams to have gossip-about-gossip. I'm surprised people do not discover it.
-
Another approach is to maintain all operations for a particular document version in anordered log, and to append new operations at the end when they are generated. To mergetwo document versions with logs 𝐿1 and 𝐿2 respectively, we scan over the operations in𝐿1, ignoring any operations that already exist in 𝐿2; any operations that do not exist in 𝐿2are applied to the 𝐿1 document and appended to 𝐿1 in the order they appear in 𝐿2.
This much like Chronofold's subjective logs.
Do the docs need to be shared in full? The only thing we need is delta ops.
-
Peritext works bycapturing a document’s edit history as a log of operations
How that works is not mentioned.
I guess ops are collected into logs, per member, based on their IDs.
A step short from having gossip-about-gossip.
-
but since a given client never uses the same counter value twice, the combination ofcounter and nodeId is globally unique
What stops him?
-
Another area for future exploration is moving and duplicating text within a document. If twopeople concurrently cut-paste the same text to different places in a document, and then furthermodify the pasted text, what is the most sensible outcome?
-
span can be deleted once causalstability [2] has ensured that there will be no more concurrent insertions into that span
-
Fig. 4
Uhh, I'd imagine "remove" would refer to "bold" annotation.
Otherwise, there can be another "bold" with t < 20, that would be accidentally removed.
Syntactic intent is not preserved.
-
For example, a developer mightdecide that colored text marks should be allowed to overlap, with the overlap region rendering ablend of the colors
That would be better for user to decide.
I think a good default is to express semantics explicitly.
I.e., for Bob to not automatically state his utterance as important just because it's atop of Alice's, that she considers important.
If Bob tries to reword - ok. If Bob want to add - no.
-
No
Given Bold, Italic, Colored are syntactic representation of semantics that we do capture - they can overlap.
Moreover, in Bob's user-defined mapping from semantics to syntax, Bob's "important" can be bold, while Alice's "important" can be italic.
-
Conflicts occur not only with colors; even simple bold formatting operations canproduce conflicts
Again, let them capture semantics.
Say, "Alice considers "The fox jumped"" as important. Alice changes mind, only "The" is important. Bob considers "jumped" as important.
Result: Alice considers "The" important. Bob considers "jumped" important.
-
Consider assigning colored highlighting to some text
Color is meant to convey some semantics. Like "accent", or "important". These semantics can coexist, just like italic and bold.
So a solution may be to: 1. Let users express semantics of their annotations 2. Give user-customizable defaults of how they are to be rendered.
Ensuring, that semantics's render is composable. I.e., it conveys originally asigned semantics.
-
Furthermore, as with plain text CRDTs, this model only preserves low-level syntactic intent,and manual intervention will often be necessary to preserve semantic intent based on a humanunderstanding of the text
Good remark of syntactic vs semantic intent preservation.
Semantics are in the head of a person, that conveys them as syntactic ops. I.e., semantics get specified down to ops.
Merging syntactically may not always preserve semantics. I.e., one wants to "make defs easier to read by converting them to CamelCase", another wants the same but via snake-case. Having merged them syntactically, we get Camel-Snake-Case-Hybrid, which does not preserve any semantic intent. The semantics intent here are not conflict-free in the first case, though.
Make defs readable | | as CamelCase as Snake Case | | modify to CC modify to SC
They diverged at this point, even before getting to syntactic changes.The best solution would be to solve original problem in a different way - let defs be user-specific. But that's blue sky thinking. Although done in Unison, we do have syntactic systems around.
So staying in a syntactic land, the best we could do is to capture the original intent: "Make defs readable".
Then we need a smart agent, human or an AI, specify it further.
-
With this strategy, the rendered result is
-
The key idea is to store formatting spans alongside the plaintext character sequence,linked to a stable identifier for the first and last character of each span, and then to derive the final formattedtext from these spans in a deterministic way that ensures concurrent operations commute
I.e., let's capture user's intent as ops, not their result.
-
-
arxiv.org arxiv.org
-
Privacy is realized by the group founder creating a specialkeypair for the group and secretly sharing the private group key with every new group member.When a member is removed from a group or leaves it, the founder has to renew the group’s keypair
Have locks on data is a nice idea.
But given we have dissemination/disclosure among friends only, do we need to encrypt the blocks? Given communication channels are encrypted.
-
However, by doing so the sender mayreveal additional information through the block’s hash pointers, e.g. the identities of other groupmembers
Well, when sharing such a block off-group, you may skip transmitting its deps. In Social Networking that may be alright. And when off-group agent gets accepted to group, he's able to get the stuff below.
However, that does complicate piggybacking, as it'll be seen that the previously off-group agent has some block (but actually he doesn't have its deps).
-
reserved words
Perhaps a sort of protobuf is better.
-
A group creator can invite other agents to become members and remove members atwill.
Goes against democratic principles.
A democratic way will be to raise a BAN poll.
-
Thegrassroots WhatsApp-like protocol WL employs a hypergraph (a graph in which an edge mayconnect any number of vertices). A hyperedge connecting agents 𝑃 ⊂ Π means that the agents in 𝑃are members in a group represented by the hyperedge
I.e., an edge of a hypergraph is a set of vertices.
This is akin to a pub/sub topic.
-
SMS
-
has an IPaddress
Multiaddr could be used instead, to aid connectivity
-
Inpractice, an agent is an app running on a smartphone
Agent = process
-
Federated systems aimto distribute control, but federated servers are still controlled autocratically
-
Note that Grassroots Social Networking requires dissemination, and Grassroots Cryptocurrenciesrequire also equivocation exclusion, but neither require consensus. Consensus is needed only byhigher-level applications that employ “on-chain” governance such as grassroots social contracts [7 ],the grassroots counterpart of miner-operated smart contracts, and grassroots representative assem-blies (in preparation).
Consensus is required for smartcontracts and governance.
Payments and social networking require weaker equivocation-exclusion.
-
and if located behind a firewall that preventssmartphones from communicating directly,
Huh, such firewalls exist? I thought they can be hole-punched.
-
In particular, adeep-fake payload that is not attributed to its source can be promptly filtered as spam
^
-
However, sinceevery block in GSN is signed, when one breaches privacy within the protocol the breach carriestheir signature so the culprit can be identified.
What stops a culprit to send off-group a message that is not his own? We can only achieve the "culprit detection" by addressing and signing every message we send to A. This is a lot of re-signing. And we won't have a convergent DAG.
-
A rather elaborate set of protocols and infrastructure (named STUN, TURN, TURNS, ICE)is needed to overcome these Internet limitations.
And that is not enough if one's (or is it both?) behind a symmetric NAT.
-
Furthermore, each block sent includes the most recent IP address of the sender,allowing agents to keep track of their friend’s changing IP addresses.
Perhaps better to attach a new IP address to a message once it does change. What's the point in telling over-and-over the same IP?
-
Every so often, an agent 𝑝sends to every friend 𝑞 every block 𝑝 knows and believes that 𝑞 needs, based on the last blockreceived from 𝑞.
^
-
Agents communicate only with their friends
More like an edge gives a communication path.
A->B (A follows B) - B can talk to A.
A<->B - B can talk to A, A can talk to B.
-
However, their exclusion is not required in social networking, and hence social networking protocolscan be simpler than payment systems protocols
I.e., Equivocation exclusion is not required for social networking.
-
Grassroots Social Networking safety implies that each member can be held accountable to theirown utterances, as well as to utterances that they forward. As Grassroots Social Networking hasno controlling entity that can be held accountable in case members of the social network breakthe law, accountability and law enforcement in Grassroots Social Networking are more similarto real life then to the social networks we are familiar with.
I.e., protocol creators are not responsible for how it's used.
-
In WhatsApp, members of a group must trust the serviceto correctly identify the member who authored an utterance, and utterances forwarded from onegroup to another have no credible attribution or context
^
-
In existing social networks, utterances by members do not carry intrinsic attribution orprovenance. Hence, Twitter members must trust the social network operator to correctly identifythe authorship of a tweet
^
-
As a screenshot with a tweet could easily be a fake, an author of a tweetcan later repudiate it simply by deleting it, and no proof that the tweet ever existed can be provided,except perhaps by the operator itself.
^
-
Naturally, an actual Grassroots Social Networking application may integratethe two protocols to provide both public feeds and private groups
Perhaps better to have a permissions mechanism that is generic to express both cases, and more, so folks can manage it flexibly as they need.
-
The WhatsApp-like network has private groups, members of each group being both the authors andfollowers of its feed
This couples two things: read permissions, write permissions.
Having them defined separately and explicitly, group's empowered with flexible controls.
E.g., as in OrbitDB's policies.
-
The Twitter-like network has public feeds
So this is a kin to pub/sub, with single authorized publisher.
-
friendsneed
"want" rather?
"need" would be for refs of a message you don't have. But then such a message could have been required to come with deps.
-
, free of third-party control
E.g., Airbnb that may refuse access to service because you're from country X, despite that host is willing to accept you.
Tags
- WL
- confused
- ban
- privacy
- grossroots
- autocracy
- sharing private messages
- sharing
- agent
- federation
- hypergraph
- address
- absence of responsibility by protocol creators
- encryption
- problem
- discovery
- grassroots social networking
- following
- event authenticity
- p2p
- data model
- third-party control
- refs disclosure
- event self-descriptive
- SMS
- culprit detection
- permissions
- cordial dissemination
- connectivity
- event persistence
- todo
- derived content authenticity
Annotators
URL
-
-
Local file Local file
-
The consensus is reached in the same way as fortransactions i.e. using hasgraph consensus algorithm. The onlydifference is, that the concerning events in the hashgraph nowcontain other type of data instead of transactions
Not necessarily, how to store
received event
s is an implementation detail. One could dump them in an array on a side. Can be as efficient as array of pointers to events. Where idx of this array is event's position in total order. -
DL
-
-
arxiv.org arxiv.org
-
Composing Implementations
Any
correct
implementation
can be composed with any other (compatible)correct
implementation
, and it is guaranteed to becorrect
. -
This implies that any correct run of the imple-mentation that stutters indefinitely has infinitely many opportunities to activatethe specification. Under the standard assumption that an opportunity that ispresented infinitely often is eventually seized, a live implementation does notdeadlock as it eventually activates the specification.
-
Live
I.e., there is a possible further computation from
y
toy'
, as well as fromsigma(y)
tosigma(y')
.I.e., from any TS' computable mapped state
y
there is a computable mapped statey'
. -
Complete
Any compute in a TS can be performed in an implementing TS TS'.
I.e., any compute in TS maps to compute in TS'.
I.e., any TS compute is translatable to TS'
-
Safe
I.e., any compute in an implementing TS TS' can be performed in TS.
I.e., any compute in TS' maps to compute in TS.
I.e., any TS' compute is translatable to TS.
-
implementedtransition system (henceforth – specification),
specification
is an implementation of a TS by a TS'. -
An implementation is correct if it is safe, complete and live.
-
Given two transition systems T S = (S, s0, T ) and T S′ = (S′, s′0, T ′) an im-plementation of T S by T S′ is a function σ : S′ → S where σ(s′0) = s0.
-
empty if s = s′
empty
meaning,noop
\self
?I guess any
s
has suchempty
transition for it. -
Also note that T and T f are not necessarydisjoint, for the same reason that even a broken clock shows the correct houronce in a while
Huuh?
-
We denote by s ∗−→ s′ ∈ T the existence of a correctcomputation (empty if s = s′) from s to s′
-
A transition in T f \ T is faulty, and a computation is faulty if it
-
A transition s → s′ ∈ T is correct, and a computation of correct transitionsis correct.
-
a run of T S is a computation that starts froms0.
-
A computation of T S is a sequenceof transitions s −→ s′ −→ · · · ,
-
Atransition system T S = (S, s0, T, T f ) consists of a set of states S, an initialstate s0 ∈ S, a set of (correct) transitions T ⊆ S2 and a set of faulty transitionsT f ⊆ S2. If T f = ∅ then it may be omitted
-
the transitions over S are all pairs (s, s′) ∈ S2, also written s → s′.
-
Given a set S, referred to asstates,
-
◦
?
-
and σ32 :S3 → S3
S3 -> S2 ?
-
→
What does * mean?
-
-
decentralizedthoughts.github.io decentralizedthoughts.github.io
-
TL;DR: Decoupling data dissemination from metadata ordering is the key mechanism to allow scalable and high throughput consensus systems. Moreover, using an efficient implementation of a DAG to abstract the network communication layer from the (zero communication overhead) consensus logic allows for embarrassingly simple and efficient implementations (e.g., more than one order of magnitude throughput improvement compared to Hotstuff).
I.e., collecting data of how processes talk is cheap and preserves what happens on the network. Consensus can be made locally based on that info. Damm simple, data FTW.
-
-
arxiv.org arxiv.org
-
Every p-block with a payment in r-coins by a correct trader p ̸ = ris eventually approved or disapproved by an r-block [provided p and r are friends or have acommon friend in SG(B)]a.
Strange that you need to have a friend-path in order to use
r
's coins. I'd expectr
to accept&approve a message from me, given I hold his coin (which he can see from my message). -
An r-block b that repays a redemption claim with comment (redeem, P ), P =[p1, p2, . . . , pk], k ≥ 1, has a payment in pi-coins, i ∈ [k], provided the balance of r does notinclude any pj -coins for any 1 ≤ j < i at the time of creating b, and has a payment in r-coins,r /∈ P , provided the balance of r does not include any P -coins at the time of creating b
Why have signed coins?
Makes it possible to track which coins been equivocated.
But what's the use for it?
What's the difference between "you can't use these specific coins as they were equivocatedly used already" and "you can't use these opaque coins, as they are in equivocation"?
Later, at least, may succed given equivocation issuer have enough balance for both. Although then there's no point in creating equivocation in the first place. So nevermind, won't happen, except by silly equivocators.
-
An r-block b with an empty payment and comment (disapprove, h′) pointsto an r-coin payment block b′, where h′ points to the reason for disapproval: To b′, if it isunbalanced, or to a block b′′ equivocating with b′
Again, this can be derived out of DAG. Seems redundant.
It would somewhat spare computation, as one can check equivocation by following a pointer, but then he would need to ensure that both equivocated blocks are observed by a self-parent chain of the "DISAPPROVE" issuer.
-
An r-block b with an empty payment and comment approve points to balancedr-coin payments block b′, where b does not observe a block equivocating with b′
What's the point of explicit approvals if it can be derived out of DAG?
It won't spare computation, as one would still need to go through DAG and ensure payment's balanced and equivocation-free. Can't trust the issuer of "APPROVE".
-
Given a blocklace B and two agents p, r ∈ Π, the r-coins balance of p in B isthe sum of r-coins payments accepted by p in B minus the sum of r-coins payments issued by p in B.
Great, so r-balance of
p
is derived by the history of ops regardingr
. So no need forp
to calculate it and add to every op, would be redundant. Not sure the derivation is the proposed protocol though. -
Finality: A p-block consumes a non-p-block b′ with a payment to p only if r approves b′.
Would be nice to have finality optional. As to not incur round-trip to a possibly offline
r
. Double-spends will be detected and punished. Given the value of double-spend spend is less than a cost - no incentive to do so. -
and only if r does not have enough p1 coins then r pays any remainder inp2 coins, and only if r does not have enough p2 coins then r pays to p any remainder in r-coins
This behavior needs to be specified more strictly.
I'd assume
r
would be in charge to explicitly describe how he wants redemption to happen. -
not letting
More like "not being able", as it's not up to him, he can't reject redemption.
-
consisting of r-coins, which can be thought of as IOUs issued and signed by r
Why do coins need to be signed?
-
The black agent mints a black coin, increasing its balance from 3 to 4 coins
Why to capture
4
? Ops likeburn(10)
,mint(1)
do the same, yet being more semantic, as they convey what happens, rather than the result.E.g., when green has 3 green_coins, and we see
send(1, green_coin, (to) black), send(3, green_coins, (to) green)
did green just miscalculated his balance (should be 2), or did he sent and minted one at the same time? -
C
That looks messy, accidentally so, it seems.
-
Green agent only needs to REDEEM(green_coin) op to convey what he wants.
-
Self-payments are redundant.
-
Links other than self-parent and other-parent(s) are redundant. You can derive anybody's balance out of their self-parent chain.
3.1 Other-parent_s_ make the order of received messages ambiguous.
REPAY
is redundant. WhenREDEEM
is received, and given one can indeed redeem (recepient has his coin at the moment of receival) - the REDEEM should be automatic. I.e., plainly observing thatREDEEM
been accepted by recepient is enough to derive out of it one of 1) it's a suffessfull redeem 2) it's a failed redeem.
-
-
and the red agent acceptsthe payment, increasing its balance to 6 black coins.
Why does he need to explicitly accept? Can't it be done by default? Can he reject?
-
The black agent approves the payment
Why does he need to approve? It is a mean of equivocation detection. But it requires all coins going through its creator. Incurring latency and possible indefinete out-of-service as creator goes offline.
Why is it not optional? Like we can exchange coins with recepient directly, and he may come to redeem it later, if he wishes, detecting eqiuvocation at that point.
Some services, that offer say a cup of coffee, would be willing to take the risk of loosing $5 of value on to-be-detected equivocations. Since equivocators will be punished severily that does not worth 5$ of value. So they can be rest assured that nobody's gonna do that.
Now this example holds if coffee provider prices in currency other than its own, say bank's.
And banks are generally online. But still. Why force it? Let them do a round-trip to currency owner at their choice, a tradeoff that's up to them.
-
decreasing its balance to 2 black coins
Why does red agent need to issue
pay
to itself?What red agents holds after he transferred 1 black coin can be derived from history his ops.
We can't trust what he issues, he may issue to self 1000 black coins. So we'd need to go check history whether he computed it right.
But then again, if we need to do that, why issue an explicit payment to self?
-
Agree to redeem any domestic coin issued in return for any foreign coin held. Forexample, Alice must agree to a request by Bob to redeem an Alice-coin Bob holds against any coin heldby Alice.
The device of Alice may be offline, e.g., smartphone discharged. We can't assume constant connectivity.
-
eachpricing their goods and services in terms of their own personal coins. Next, assume that every two villagersexchange 100 personal coins with each other
Pricing in your own coins means personal coins may not match in value behind them. One may offer a cup of coffee for 1 coin, another for 5. Simply exchanging 100 coins with each other would mean one'll get 1/5 of value from this exchange. So 1:5 exchange would be needed. But how to know that in advance?
-
If all agents must obtain and maintain a complete copy of the entire data structure in order to operate it shouldbe called replicated ; it should be called distributed if different agents access, maintain and store different parts ofthe data structure. Similarly for distributed ledgers vs. replicated ledgers, with blockchains falling under the secondcategory. Note that sharded blockchains are replicated, as an agent must obtain all shards in order to operate onthe blockchain
distributed ledger vs replicated ledger
-
-
arxiv.org arxiv.org
-
lest any tem-porary decline in personal productivity would result in theperson going broke
Couldn't he spend less? I mean if he doesn't go below his minimal sustainability expenses, he can trade what's left.
-
Minting: Each agent p mints (i.e. creates initial NFTs with)its own p-coins, as many as it pleases
An agent may create as many agent's coins as he pleases.
-
Economically, sovereign cryptocurrenciesprovide for grassroots liquidity without external capital or credit,as mutual credit lines can be established via sovereign coinexchange among members of the cryptoeconomy
Sovereign cryptocurrencies allow getting a credit from grassroots. You can convince people that you're a good enterpreneur, they'll exchange their tokens for your yet-to-be-built organization tokens. Possibly exchanging with a discound from your organization, so they can make profit later on, when it's established.
-
-
-
Weshow that the blue leader is ratified by any subsequent cordial leader
The second supermajority is a set of messages that super-ratifies some message. But here we don't make use of super-ratification. Next leader may observe just one message that super-ratifies.
-
for any p, q ∈ P and anyp-block b ∈ B there is a q-block b′ ∈ B such that b′ ≻ b
Didn't get it. I'd expect that all blocks created by by these guys would refer to their previous blocks. Here the definition seems to say that one guy needs to ref to another's guys blocks, which is not "mutual".
-
ratified by ablock b if it is ratified by the set of blocks [b
I.e., ratification is a transitive closure.
-
if [B] includes a supermajority of blocks that approve
I suspect, equivocated blocks are excluded from
|B|
.I.e., do not contribute their ratification to block
b
. -
For each wave, one of the miners is elected as the leader, and if the first round of thewave has a block produced by the leader, then it is the leader block.
What happens when many users are offline?
(depends how many, if there's not enough to form supermajority - no messages will be created at all)
If there's say 1/3, then I guess it'll be 1/3 of fail-to-select-a-leader attempt.
Also, members could have different stake. Then there may be say 1/5 members that hold supermajority stake, they're online, but the rest 4/5 is not. Then, I guess, there'll be 4/5 failed-to-select-a-leader attempts, on average.
-
When a waveends, i.e., when the last round of the wave is cordial, the leader block becomes final if it hassufficient blocks that approve it, namely, it is not equivocating and there is a supermajoritywhere each block observes a supermajority that observes the leader block
"supermajority that observes supermajority that observes the leader". How likely that there will be?
-
Correct minersare cordial in that they wait for round r to attain a supermajority before contributing ablock to round r + 1.
Uff, this gets vague. "Wait" as in "buffer received events"?
But then how do these events get propagated, when everyone's buffering? I thought only events that are accepted into blocklace are propagated.
What stops accepting events right away, and propagating them further? Defining rounds as Hashgraph does. Because this is basically the strive for the same end - a block gets r+1 round when it sees that supermajority sees supermajority.
The thing with this algo is that the communication/dissemination between rounds seems to be hidden / not included in the DAG. What' the point in doing so?
We have less information on our hands of what happened in the system, that may be of value.
Also, by not including communication we miss the oportunity to add more ops when sending stuff to others.
-
A set of blocks by more than 12 (n + f ) miners is termed asupermajority
When f = 1/3, then supermajority is 2/3.
n = 3 f = 1
(3 + 1) / 2 = 4 / 2 = 2 (out of 3)
-
The depth of a block in a blocklaceis the length of the maximal path emanating from it
-
To this end, theblocklace is divided into waves, each consisting of several rounds, the number of which isdifferent for ES and asynchrony (3 and 5 rounds per wave, respectively).
^
-
In case a wave ends with no finalleader block, unordered blocks will be ordered when some subsequent wave ends with a finalleader block.
A wave may end without leder block elected.
What's the probability of that? Is it included in the reported results?
-
The use of a DAG-like structure to solve consensus has been introduced in previous works,especially in asynchronous networks. Hashgraph [ 4 ] builds an unstructured DAG, with eachblock containing two references to previous blocks, and on top of the DAG, the miners runan inefficient binary agreement protocol. This leads to expected exponential time complexity
Hashgraph's voting complexity is exponential. ?
-
-
www.swirlds.com www.swirlds.com
-
The protocol might even say that afterAlice syncs to Bob, then Bob will immediately sync back to Alice
This requirement would help to find colluders.
-
and gossips to him all the events thatshe knows. Bob then creates a new event to record the fact of that gossip
I guess Alice would only need to send Bob events that she knows he does not know.
-
When Bobgossiped to Alice, he would give her all of the events which he knew and she didnot.
How that's done?
Bob could gossip to Alice all events he knows she knew, based on his hashgraph, but it's not the same as gossiping all events he knows she knows.
Bob may have a stale view of what Alice knows.
The more up-to-date view that Bob can get is when receiving an event from Alice.
-
Data structures withgraphs of hashes have been used for other purposes, such as in Git where the ver-tices are versions of a file tree, and the edges represent changes
That's not how git works. It does use deltas heavely under the hood, but it's derived out of snapshots, which is the primary data model.
-
The red eventcan also contain a payload of any transactions that Alice chooses to create at thatmoment, and perhaps a timestamp which is the time and date that Alice claims tohave created it
Payload and timestamps are optional.
-
Alice then repeats with a differentrandom member.
After sending an event to a random peer, on completion - pick another random one.
-
Figure 1
^ middle member send his third event to his left and right member. So it's not just "send to one random". How is that specified?
-
-
-
We believe that thelack of a business model that can incentivize ‘genuine’ peer-to-peer applications and the lackof suitable architectural foundations for such applications are the culprit
^
Tags
Annotators
URL
-
-
arxiv.org arxiv.org
-
The block content isa pair 퐶 = (푣, 푃) of an arbitrary value 푣 (the block payload)and a set 푃 of the block identities of the predecessors of 푏
Since signature carries ID, referring by hash will not capture ID, wheres referring by ID will. Interesting approach.
-
the block is valid: valid(푣, ≺푏),using the definition of valid provided by the data type
^ I.e., we need to ensure validity of block's ops. This is a datatype-specific validation.
-
Contrary to current DAG-like structures that use hashesof content, a blocklace uses signed hashes from which theblock creator can be known. Not only this can aid dissemina-tion, by knowing which node is missing which blocks, butmore importantly, it can be used to detect equivocations andequivocators
Hashgraph gives all of that, as it has signatures. What's new here?
-
In-deed, the blocklace-based Cordial Dissemination protocol [7,12] employs the fact that a 푝-block 푏 by a correct node 푝 ac-knowledges all the blocks known to 푝 at the time of blockcreation
-
To be a colluder, 푝 must violate liveness, as it must refuseindefinitely to accept blocks by correct agents that acknowl-edge 푞 as Byzantine.
Perhaps keeping track of to whom events are being sent will allow to collect evidence, that a node violates liveness.
Furthermore, this can be kept local, and only reported when observed that liveness is violated. I.e., "You said that you received my message, but from others said to me later, it wasn't included. I'm reporting you now."
Having collected > 1/3 reports - node can be considered to violate liveness.
In this approach, however, any >1/3 nodes can conspire and exclude any other node they wish, without evidence, "trust us".
-
Accept the block into the blocklace, resulting in all nodeseventually knowing that 푝 is Byzantine
One pair of equivocated blocks is enough to keep for that purpose. Having learned there are two - subsequent ones can be rejected on receival. Not all nodes will know of equivocator, and will send updates to it. So these updates may not reach the community. But eventually equivocator will be consensually known and excluded.
This is a tradeoff.
Alternative is to stub eqivocated messages, so the correct messages are passed around.
-
node
Here
node
refers toprocess
/member
. -
Correct nodes create a new block in 퐵 using the identitiesof the set of maximals in 퐵 as predecessors. By definition,all the elements in this set are incomparable, forming anantichain. If that is not the case, the creator is Byzantine
Didn't get it
-
and eventu-ally excluding any new blocks created by Byzantine agents
Somebody may do some work atop a message that's in fork. What happens to this work if the block gets excluded?
Also "exclude" may mean logical deletion, if we detect nodes that are in fork, we can skip transferring it's ops, instead placing a hash, since these ops won't be used anyways (and can be rather huge, up to a max allowed size), thus preserving causality by having a malicious block around, and saving on metadata by transferring the minimum of information for causality to be preserved. (stubbing content with a hash).
-
Extant approaches no not attempt to detect equivocations.Messages from Byzantine equivocators that are not rejectedas invalid are simply accepted and treated as if they wereconcurrent operations from different correct nodes.
Not true for Hashgraph. Equivocation there is known as a "fork". Forks are detected and do affect the algorithm of virtual voting (these messages are not "seen", i.e., their ops won't be included). Hashgraph does not propose to reject these messages. I guess this is due to them potentially carrying valid ops from other peers. But overall, nothing stops ignoring Byzantine members or straight out excluding them.
-
A blocklace 퐵 is then isomorphic to a PO-Log from thepure-op framework, thus is also a pure-op CRDT
Blocklase is a pure-op CRDT.
Causality is baked into each message, but more robustly, not as a version vector, but by hashes. Thus being more suitable for a Byzantine environment.
-
were max≺ (퐵) is the set of maximal blocks in 퐵 under the≺ relation, i.e., the blocks which are not pointed from anyother block in 퐵
That's interesting. Block may refer to many blocks at once.
Curios whether Hashgraph's consensus can hold with it. It'll give inacurate timestamps. I.e., accuracy of how events been received will suffer. Perhaps we can only receive immediately events that contain ops that requrire a point of order. But overall, receiving and propagating further events right away seems to be a good strategy, since it captures more accurately what happens over-the-network. And it's more constricting, meaning it'll be easier to detect byzantine behaviour. Nodes are required to accept any valid events right away. Given we want to propagate events by gossip fast, we'd need nodes to accept and propagate their newly created event right away.
I.e., the approach of multiple blocks is not gossip-about-gossip.
There's a downside of having to accept right away. That is if we strictly comply to gossip-about-gossip, then event must point to other-parent. But if there's no other-parent, how do we get our local ops packaged and sent?
Perhaps a way is to ease the requirement of other-parent ref, then nodes can add local ops with ref to self-parent alone, and propagate them, will be alright even for a single keystroke op in text editors, although the metadata cost is somewhat high.
Perhaps metadata can be reduced down to signature. So whenever one receives an event with just signature - we know that it's an event with only self-parent ref. A well-known special case.
And when you want to accrete atop other-parent, you include a hash of it.
So the metadata cost is signature and, optionally, 1 hash.
Processing cost of deriving author out of signature, and verification is to be measured.
-
Note that the virtual chain axiom holds for correct nodessince they create blocks in sequence and include each newblock in their blocklace
Virtual chain is a kind of global chain. Nodes converge into it. There should be a self-parent chain, where forks are detectable and considered byzantine.
But perhaps gossip-about-gossip is even better.
-
Thus, there are no “dangling pointers” in a blocklace: eachidentity in each set of predecessors of a block in a blocklaceidentifies a block in the blocklace.
Well,
ia
is a hash. So it may be missing inB
. Need to ensure thatia
(and all it's transitive deps) are present inB
before accepting it, adding toB
.E.g., use Reliable Causal Broadcast.
E.g., request missing nodes, holding to a node with dangling pointers before they arrive. Optionally discarding it if deps did not get fetched after a while.
-
Weassume that the identity (public key) of the node can be ex-tracted from its signature, e.g., using ECDSA.
^
-
We remark that even if two nodes 푝, 푞 ∈ Π hold identi-cal blocklaces, and each of these nodes creates a new blockwith the same payload and same set of predecessor blocks,and therefore with the same hash, block identities will bedifferent as the hash will be signed by the different privatekeys of 푝 and 푞.
So, nothing stops byzantine members to forge that they received some event from another node.
Can be catered for by wrapping events in a message, containing recepient. This captures more data of what happens on the network. Data FTW.
-
-
arxiv.org arxiv.org
-
A block is final when subsequent blocks issuedby a supermajority of the agents approve it. See Figure 1.A
This is interesting. Finality can be derived per event / block.
-
If the block is urgent then issue an ack block.
Acks as first-class citizens of a DAG
-
Existing algorithms for payment systems, including the onesin [ 1, 6 , 11], are based on reliable broadcast (RB) [ 2] to disseminateblocks to other agents. RB is an abstraction that prevents Byzantineagents from equivocating, which in the context of a payment systemprevents Byzantine agents from doublespending
Forks may exist in RB. Having learned that every learned of a payment and it had no forks - we can accept. But solely RB seems not enough.
Tags
Annotators
URL
-
-
inria.hal.science inria.hal.science
-
An op-based CRDT is pure if mes-sages contain only the operation (including arguments, if any).
Pure op-based CRDT just propagates ops, causality is preserved by default, guranteed by the messaging API.
-
The possi-bility of a stable operation obsoleting a new arrival, in its causal future, is notconsidered, but this can easily be changed if some example shows its usefulness
If we have a stable add(v), and we receive add(v,t), the later can be made obsolete.
-
Here we not only need this to happen but also that no further concur-rent messages may be delivered. Therefore, causal stability is a stronger notion,implying classic message stability
Causal stability - a given message will be in causal past of any yet to receive messages. I.e., there are no messages for any not yet to be learned that do not have a given message in their causal past.
-
As such, a pure op-basedCRDT implementation is trivial: as when using the standard causal broadcast,the message returned from prepare, containing the operation, will arrive exactlyonce at each replica, it is enough to make effect consist simply in applying thereceived operation to the state, over a standard sequential datatype, i.e., definingfor any datatype operation o:
Prepare phase won't be needed, if we preserve context of the op, e.g., via a hashgraph of ops. So any replica can derive the state an op's been issued on.
-
Commutative datatypes reflect a principle of permutation equivalence [11]stating that “If all sequential permutations of updates lead to equivalent states,then it should also hold that concurrent executions of the updates lead to equiv-alent states”
This is a stronger requirement than SIM-commutativity.
Ops are guaranteed to commute / result is the same with no regard to order of ops.
-
Op-based CRDTs can often have a simple and compact state since they can relyon the exactly-once delivery properties of the broadcast service, and thus donot have to explicitly handle non-idempotent operations.
What stops making an op content-addressed, so it's deduplicated on multiple receivals?
-
-
github.com github.com
-
I think this would modify your trust model. Say you trusted 10 peers. If one of them was malicious, then you have 1/10 malcious peers and the majority of nodes are good so you could identify the bad node. In the changes you propose, (if I understand correctly), the 1 malicious node, could then send you 100 more malicious nodes. So then you'd be connected to 101/110 malicious peers and the malicious peers would be the majority.
A way to cater for eclipse attack can be to capture node's addresses in a hashgraph of that gossipsub topic. This way, when a new node connects to any of behaving peers, it'll get HG with addresses of others.
That will possute HG with unrelated to domain stuff however.
-
-
arxiv.org arxiv.org
-
VectorSync [31] is an enhanced version of ChronoSync[35] which uses version vectors to make synchronisationbetween peers more efficient. Version vectors are more efficientin detection of inconsistencies, than simple message digests, asmentioned earlier. However, similarly to other proposals in thearea, VectorSync needs to realise a ‘leader-based membershipmanagement’ in order to deal with active members that updatethe state of the dataset.
Y.js uses version vectors to sync p2p. Yet it's a brittle approach. No hashgraph integrity.
-
-
Local file Local file
-
Moreover, after executing an inverse opera-tion like O2, the document state can no longer be properlyrepresented by the state vector, which is only capable ofrepresenting original normal editing operations
I don't see how Undo would mess up State Vector, being just another op. State Vector bit of that user would increase.
-
-
docs.yjs.dev docs.yjs.dev
-
I get a new ClientID for every session, is there a way to make it static for a peer accessing the document?
Would be nice to have truly unique ids. E.g., a public key.
Eats more space, but can be zipped over the wire. Given there are many ops transferred.
Also could be possible to create pubkey -> int mapping per-document, so it's damm more compact. That would require consensus on this map.
-
-
Local file Local file
-
Furthermore, due to its design, the garbage collector inYATA may break late join mechanisms. This is becausewhen a user is offline for a period longer than t seconds,it will still hold references to deleted operations, while on-line users who already performed certain removals do not.Therefore, YATA does not support garbage collection for asite while it is offline.
So, whenever there's constantly > 1 users offline on a doc - can't garbage collect / compact.
-
From our practical experi-ences and the use in production, such a delay is sufficientto ensure that content will be removed safely, without anylosses that may lead to inconsistencies
User may go offline for more than 30 seconds. The approach seems brittle
-
Conceptually, an insertion marked for deletioncan be garbage collected when all sites received the removeoperation and have in their internal representation the op-eration that is to be garbage collected
.
-
We denote an insert operation as ok (idk , origink , lef tk ,rightk , isDeletedk , contentk )
That's plenty of metadata.
Why three refs? CT showed that one's enough.
Also strange that deletion mutates an op, rather than being another op. Seems it'll be hard to manage it (undo/redo).
-
Upon its creation, the operation thus gets as-signed a unique identifier which is composed of the useridand the current operation counter
It's unique as far as user behaves, not creating ops with the same id.
Hash of an op would be a good id. Although it does not come with a counter. So counter, if we need it, is in the op.
-
The downside ofthis approach is that a state vector must be transmittedwith every operation, where the size of the state vector isproportional to the number of users in a collaborative ses-sion.
.
-
COT has a simplified design, as only onetransformation function must be defined
.
-
The ideabehind COT is to save every received operation “as is” in adocument state and preprocess it afterwards given the op-eration context.
.
-
-
marijnhaverbeke.nl marijnhaverbeke.nl
-
If you tried to join two lists together, but somebody has added a paragraph between them, your change becomes impossible to execute (you can't join nodes that aren't adjacent), so it is dropped.
Strange. I'd expect user's intent to be preserved.
-
Instead of a central server calling the shots, you could use a consensus algorithm like Raft to pick an arbiter. (But note that I have not actually tried this.)
That is another step of accidental complexity
-
-
marijnhaverbeke.nl marijnhaverbeke.nl
-
Secondly, though most OT systems just represent changes as a series of insertions and deletions, mapping seems to require us to distinguish replacements from the corresponding delete/insert pair. When a replacement happens next to a given position, the position should never move across the replacement, regardless of whether you're mapping forward or backward. In order to be able to support this, CodeMirror's change representation is encoded as a series of replacements. (Insertions become replacements that don't delete anything, and deletions replacements that don't insert anything.)
Flew over my head
-
This can be derived from a sequence of individual changes, but it seems like it'd be more pleasant if changes were directly kept in that shape.
Chronofold seems to have what's wanted here
-
When a client receives conflicting remote changes, it first undoes all its local pending changes, applies the remote changes, and then the transformed form of its local changes.
Uhh, strange approach at glance. I'd expect local changes to be preserved and received changes to be transformed and applied atop.
-
OT algorithms that support decentralized editing rather resemble CRDT algorithms
I don't see it. The OT and CRDT have distinct approaches on how to converge.
OT embraces subjective views, adopting ops of others to it.
CRDT introduces a distributed data model, that every user builds upon.
-
along with data (often a logical clock) embedded in the IDs
Rather, each object contains ID + clock + author + reference to another object & what not. Hefty on metadata. CRDTs focus on optimizing that. Perhaps another approach is to ditch the distributed model and embrace subjective op logs.
-
That is where CRDTs come in. They are another approach to convergence that, contrary to operational transformation, does provide a way for us mortals to reason about convergence.
It makes a somewhat easy to grasp distributed model of a doc. Which makes it easy to sync. But building atop it client-side is a pain. It is complex. As Chronofold paper points out. Many projects folded, stating the CRDT model as the source of complexity that's been the cause.
-
And when you don't have a centralized party to determine the order in which changes get applied, you need, as far as I understand the literature, to keep data beyond the current document (“tombstones” that describe where deletions happened), to guarantee convergence.
Tombstones seem to step away from OT approach.
Where you have a separate from the current-doc representation. A DAG, from what I've seen. E.g., WOOT, CT, other CRDTs.
-
Periodically try to send those to the server, which will either accept them or, if another client sent a change first, reject them because your changes start in a base document that doesn't match the current central document.
That seems rather harsh on UX. Surely it can be done better.
Here 1. server acts as the source of truth. And 2. clients try to compare-and-swap kind of.
But we don't need 1., clients are the source-of-truth, server is a helper middle man (that should be optional)
And having 2. we would not comply to any of the consistency models of OT - e.g., intents are preserved, happily merging.
-
But it does drag in a lot of problems, even outside of the document convergence—peers have to store the document along with, depending on the technique used, its entire history.
This may not be the case. When peers know they're in sync - they can snapshot and dispose of the ops.
-
-
en.wikipedia.org en.wikipedia.org
-
Consistency models
^
-
Moreover, the ordering is effectively determined by the effects of the operations when they are generated
I don't see how that makes ops "admissible". Simply by reordering we won't get preservation of intent.
E.g.,
"abbcd"
peer1 and peer2 in parallel delete the second duplicate
b
.No matter how we order them, we have:
[delete(3), delete(3)]
Intent of peers: "abcd"
Playback of log: 1. "abcd" 2. "abd"
Doesn't look like we preserved the intent - delete(position) is not admissible, in general case. It's context-dependent. No matter the order.
-
Consequently, the total order becomes application specific
Well, it's not 'total order' anymore then, is it?
More like a subjective operations log. See Chronofold.
-
The invocation of every operation is admissible in its execution state
Then we can't have delete(position) operation. As it context-dependent.
I.e., ops need to be self-contained. delete(position) becomes delete(char-id) - whoa, now we have CRDTs.
-
The above CSM model requires that a total order of all objects in the system be specified
I don't see that.
What CSM does, as it seems to me, is to specify/extend the "Intention preservation" of CCI.
Moreover, total order has nothing to do with "intention preservation". Ops that been issued in parallel can be put in total order - yet it does not give convergence of intent.
E.g.,
"abbcd"
And peer1 wants to change
c
toC
.Whereas peer2 wants to remove the second
b
.[delete(3), delete(4), add(4, char: "a")]
Playing the ops: 1. "abcd" 2. "abc" 3. "abcC"
Intention of
c
->C
is not preserve, despite having total order. -
Second, it was defined as operation context-based pre- and post- transformation conditions for generic OT functions
This solution seems to aim to preserve intention (same result of an op in a different context) as trying to capture some host context and try to adopt op+some_context to the target context.
Which seems rather unnecessary if you would transfer op+host_context as is, the receiving party will be able to adopt it.
-
-
-
The Awareness CRDT must only apply updates if the received clock is newer / larger than the currently known clock for that client
Clock, meaning Lamport one? Otherwise, with subjective clocks, I don't see how that works.
-
we always exchange the whole state of all locally known clients
Exchanging deltas seems fine too
-
-
docs.rs docs.rs
-
This collaborator can then deserialize it back and generate an update which will contain all new changes performed since provided state vector
Does receiver need to trust the sender that the provided update does indeed contain all the missing ops?
Tags
Annotators
URL
-
-
pfrazee.com pfrazee.com
-
JSON-Schema with namespaces
Not convinced that it turned out simpler and easier than sticking with RDF stuff. May be biased with some prior RDF knowledge though.
-
-
queue.acm.org queue.acm.org
-
It should be obvious by now that causal histories work but are not very compact
Also, while a causal history includes every event, it's by a non-hash-based id. So no actual content is available.
Using hashes to refer to content would allow to be context-free. Any replica would know the stuff they're talking about.
Not compact, yes. Just two hashes are enough, in fact. ;)
-
-
arxiv.org arxiv.org
-
to work withother linearizations we have to build their respec-tive chronofolds.
Is this possible? I thought no.
It doesn't seem that RCT captures what's in subjective logs.
Version vectors would seem to allow it. But I think we don't have them in RCT.
-
Thatcosts O(N ) and from that perspective we mightbe tempted to store that mapping in a hash map
Alternativey, have a vec for each author (yourself included).
So there would be a vec of author
y
, where unberk
index is index ina
's log.Althought having no RCT to start with would be better.
-
Next, it has to findthe op’s position in the weave and relink the linkedlist to include the new op at that position
Seems this is not on a hot path. Can be done in parallel, without blocking user's input. Once links are established, it can be atomicly applied. This will block.
-
Weave is the most natural data struc-ture for diffing and merging, but editing a weavealso requires splicing
RCS seems better, does not require splicing.
-
CRDT overheads and complexity are rooted inthe use of per-character ids and the need to mapthem to positions in the weave and the text
Isn't it already a delta weave?
-
The top issue with a weave isthat it needs to be spliced on every edit (i.e. rewrit-ten in full), very much like a plain string
Here
weave
refers to interleaved deltas (SCCS weave).And
splice
refers toinsert
.Meaning, that in order to add delta, we'd need to insert it in some position of a file. Which would lead to moving characters around. Hence the comparison with a plain string.
How this works is described here, in RCS, that seems to be a successor of
interleaved deltas
(SCCS) approach. -
CT parent
?
-
for all β ∈ proc(R).
Got me confused, as previously
b
's been referning to an exact process. Perhaps a genericp
could be introduced. -
Atimestamp is an ordered pair t = ⟨n, α⟩ where α isthe author also denoted by auth(t), and n is theauthor’s index also denoted by andx(t).
Resembles
pointstamp
of timely dataflow(?).
-
-
dl.acm.org dl.acm.org
-
Merged deltas work as follows
^
-
Fig. 2: A r e v i s i o n t r e e w i t h f o r w a r d a n d r e v e r s e d e l t a s .
^
-
-
-
increment: 2
Nice that it operates on deltas. Although I wish the deltas would be the source-of-truth.
-
For example, we can use it to inform observers of this model that its state has changed. Let's add that to our example, by calling cx.notify().
Huh. Would be nicer if that model implemented some sort of
Watchable
trait. Akin to Clojure'satom
s. So others can subscribe to, and get notified on change automatically. So we can't shoot ourselves in the foot by forgetting to do that manually. -
The handle doesn't truly own the state, but it can be used to access the state from its true owner, the AppContext.
Resembles
cursor
abstraction of tonsky/rum
-
-
-
If the subsequent frame contains the same text-font pair, the shaped glyphs get reused.
Perhaps we could reuse even larger repeating patterns, such as words, since in programming we tend to operate with such. (programming language reserved words, such as
if
when
match
, and defs a user creates, such asmyCoolVar
.Though they could be split across multiple lines, as myCool- Var, although perhaps that is not a desired feature for an editor to do.
-
We experimented with Patrick Walton's Pathfinder crate, but it wasn't fast enough to achieve our performance goals
wgpu any better?
-
It's a tight deadline
For a text editor, it doesn't seem like one.
-
A modern display's refresh rate ranges from 60 to 120 frames per second
As of now, there are displayes with 240Hz. (4.1(6)ms/frame)
But aiming to get smooth 120fps 4K is a good minimum.
However, for a text editor, being able to run 240Hz seems to be a resonable demand.
-
-
-
but we may eventually introduce the ability to undo operations of collaborators
Or, rather, a client could 'reject' some contributions. I.e., be in power to accept contribution of others.
-
A shared global stack of edit operations isn't enough
Having these ops contain author, one could undo their own ops. And I bet authorship is preserved.
The thing is that
shared global stack
is not useful to beshared
, rather somestack
can derived on each client in order to play.But then some things could be played it paralell, So instead we're better of with some sort of AST. It could be derived out of
global stack
, but then we could construct an AST in the first place, havingops
to come with theirdeps
, as we have with CRDTs.That is better, given that cost of AST is less than the cost of playing sequentially. I.e., cost of AST (increased size and complexity) worth the gainst we get from parallel play.
-
-
protocol.ai protocol.ai
-
Dr. Victor Grishchenko, Oleg Lebedev, Yuri Syrovetskiy and Nikita Prokopov
Powerful team. What's the outcome?
-
- Mar 2024
-
rust-lang.github.io rust-lang.github.io
-
map_err
More like
alter_error
, orupdate_error
.I see
map
as a transducer, suitable to run on sequences.Whereas here we don't have a sequence.
-
-
rust-lang.github.io rust-lang.github.io
-
Tasks are the top-level futures that have been submitted to an executor.
From what I understand, Tasks are not the top-level futures, but rather any Future that's being executed.
So there may be:
async { async { async { }.await }.await }.await
Where each async block is a Future, that's been wrapped by a Task on.await
, and will drive to completion, be it returning right away, or hanging and calling.wake()
on it's parent when it's done.
-
-
rust-lang.github.io rust-lang.github.io
-
OS threads don't require any changes to the programming model, which makes it very easy to express concurrency. However, synchronizing between threads can be difficult, and the performance overhead is large. Thread pools can mitigate some of these costs, but not enough to support massive IO-bound workloads.
^
-
-
book.async.rs book.async.rs
-
Tasks are assumed to run concurrently, potentially by sharing a thread of execution.
Why?
-
block_on
Why not call it
join
, as for threads?
-
-
doc.rust-lang.org doc.rust-lang.org
-
Option<Arc<Node<T>>
Why not
LinkedList<T>
?
-
-
doc.rust-lang.org doc.rust-lang.org
-
Collects all the items from an iterator into a collection.
Yay, Rust's soon to have Clojure's
into
for transducers! -
&mut
Why does it need it to be mutable? It doesn't mutate it.
-
-
doc.rust-lang.org doc.rust-lang.org
-
.iter().map
Why do we need
iter
beforemap
?Couldn't
map
do theiter
, if needed?That could even be done at compile time, to reduce run-time overhead, giving users a more comfy/familiar
map
interface.
-
-
arxiv.org arxiv.org
-
if t ≠ ref(t)
Meaning, it's possible to ref to itself?
-
- Feb 2024
-
www.swirlds.com www.swirlds.com
-
The whitened signature is the signature XORed with thesignatures of all unique famous witnesses in the received round.
^
-
- Jan 2024
-
clojure.org clojure.org
-
If a pure function mutates some local data in order to produce an immutable return value, is that ok? It’s an interesting question. Clojure data structures use mutation every time you call, e.g. assoc, creating one or more arrays and mutating them, before returning them for immutable use thereafter. The reason is performance - you simply can’t get as fast using only pure functions and immutable data. Once constructed and shared however, being immutable and persistent is essential to robust programs. The things Clojure mutates internally are small, newly allocated arrays that constitute the internal nodes of its data structures. No one ever sees the arrays.
Functional interfaces are enough for FP. Inside you can mutate, noone will know, it does not affect in=>out result. And that's what FP cares about.
-
-
www.swirlds.com www.swirlds.com
-
Once round r is settled, thefuture rounds will reshuffle, and the calculations for round r + 1 famous witnesseswill be done using the new stake record.
Change to stake record that happened by concluding round r will not affect round r events, they will use the previous stake record. Events that are r+1 will use the new one.
-