mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Up to TwoBlockChains in crypto
This commit is contained in:
parent
ffeaf20e64
commit
fb408ab80d
1 changed files with 305 additions and 10 deletions
315
crypto.py
315
crypto.py
|
@ -730,7 +730,6 @@ class InitialProtocol(Scene):
|
||||||
self.items.add(item)
|
self.items.add(item)
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
class AddFraudulentLine(LedgerScene):
|
class AddFraudulentLine(LedgerScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.add_ledger_and_network()
|
self.add_ledger_and_network()
|
||||||
|
@ -2979,12 +2978,10 @@ class DistributedBlockChainScene(DistributedLedgerScene):
|
||||||
).shift(LEFT)
|
).shift(LEFT)
|
||||||
return creatures
|
return creatures
|
||||||
|
|
||||||
|
|
||||||
class IntroduceBlockCreator(DistributedBlockChainScene):
|
class IntroduceBlockCreator(DistributedBlockChainScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"n_block_creators" : 3,
|
"n_block_creators" : 3,
|
||||||
# "n_pow_guesses" : 60,
|
"n_pow_guesses" : 60,
|
||||||
"n_pow_guesses" : 10,
|
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.add_network()
|
self.add_network()
|
||||||
|
@ -3213,6 +3210,7 @@ class IntroduceBlockCreator(DistributedBlockChainScene):
|
||||||
new_chains = self.get_distributed_ledgers()
|
new_chains = self.get_distributed_ledgers()
|
||||||
block_target_group = VGroup()
|
block_target_group = VGroup()
|
||||||
anims = []
|
anims = []
|
||||||
|
arrow_creations = []
|
||||||
for old_chain, new_chain in zip(old_chains, new_chains):
|
for old_chain, new_chain in zip(old_chains, new_chains):
|
||||||
for attr in "blocks", "arrows":
|
for attr in "blocks", "arrows":
|
||||||
pairs = zip(
|
pairs = zip(
|
||||||
|
@ -3221,7 +3219,7 @@ class IntroduceBlockCreator(DistributedBlockChainScene):
|
||||||
)
|
)
|
||||||
for m1, m2 in pairs:
|
for m1, m2 in pairs:
|
||||||
anims.append(Transform(m1, m2))
|
anims.append(Transform(m1, m2))
|
||||||
anims.append(ShowCreation(new_chain.arrows[-1]))
|
arrow_creations.append(ShowCreation(new_chain.arrows[-1]))
|
||||||
block_target = self.block.copy()
|
block_target = self.block.copy()
|
||||||
block_target.replace(new_chain.blocks[-1], stretch = True)
|
block_target.replace(new_chain.blocks[-1], stretch = True)
|
||||||
block_target_group.add(block_target)
|
block_target_group.add(block_target)
|
||||||
|
@ -3231,18 +3229,315 @@ class IntroduceBlockCreator(DistributedBlockChainScene):
|
||||||
))
|
))
|
||||||
anims.append(Broadcast(self.block, n_circles = 4))
|
anims.append(Broadcast(self.block, n_circles = 4))
|
||||||
anims.append(FadeOut(self.hash_group))
|
anims.append(FadeOut(self.hash_group))
|
||||||
|
anims.append(ApplyMethod(
|
||||||
|
self.block_creators[0].change, "happy"
|
||||||
|
))
|
||||||
|
|
||||||
self.play(*anims, run_time = 2)
|
self.play(*anims, run_time = 2)
|
||||||
|
self.play(*it.chain(
|
||||||
|
arrow_creations,
|
||||||
|
[
|
||||||
|
ApplyMethod(
|
||||||
|
pi.change, "hooray",
|
||||||
|
pi.block_chain.get_right()
|
||||||
|
)
|
||||||
|
for pi in self.pi_creatures
|
||||||
|
]
|
||||||
|
))
|
||||||
|
self.dither(3)
|
||||||
|
|
||||||
|
class MiningIsALottery(IntroduceBlockCreator):
|
||||||
|
CONFIG = {
|
||||||
|
"n_miners" : 3,
|
||||||
|
"denomination" : "LD",
|
||||||
|
"n_guesses" : 90,
|
||||||
|
"n_nonce_digits" : 15,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.add_blocks()
|
||||||
|
self.add_arrows()
|
||||||
|
self.make_guesses()
|
||||||
|
|
||||||
|
def create_pi_creatures(self):
|
||||||
|
IntroduceBlockCreator.create_pi_creatures(self)
|
||||||
|
miners = VGroup(*[
|
||||||
|
PiCreature(color = GREY)
|
||||||
|
for n in range(self.n_miners)
|
||||||
|
])
|
||||||
|
miners.scale(0.5)
|
||||||
|
miners.arrange_submobjects(DOWN, buff = LARGE_BUFF)
|
||||||
|
miners.to_edge(LEFT)
|
||||||
|
for x, miner in enumerate(miners):
|
||||||
|
label = TextMobject("Miner %d"%(x+1))
|
||||||
|
label.scale(0.7)
|
||||||
|
label.next_to(miner, DOWN, SMALL_BUFF)
|
||||||
|
miner.label = label
|
||||||
|
self.add(label)
|
||||||
|
self.miners = miners
|
||||||
|
return miners
|
||||||
|
|
||||||
|
def add_blocks(self):
|
||||||
|
self.add(self.miners)
|
||||||
|
|
||||||
|
blocks = VGroup()
|
||||||
|
for miner in self.miners:
|
||||||
|
block = self.get_block()
|
||||||
|
block.stretch_to_fit_height(2)
|
||||||
|
block.stretch_to_fit_width(3)
|
||||||
|
block.next_to(miner, RIGHT)
|
||||||
|
|
||||||
|
payments = self.get_payments(miner)
|
||||||
|
payments.scale_to_fit_height(1)
|
||||||
|
payments.move_to(block)
|
||||||
|
block.add(payments)
|
||||||
|
|
||||||
|
prev_hash = TextMobject("Prev hash")
|
||||||
|
prev_hash.highlight(BLUE)
|
||||||
|
prev_hash.scale_to_fit_height(0.2)
|
||||||
|
prev_hash.next_to(block.get_top(), DOWN, SMALL_BUFF)
|
||||||
|
block.add(prev_hash)
|
||||||
|
|
||||||
|
miner.block = block
|
||||||
|
miner.change("pondering", block)
|
||||||
|
blocks.add(block)
|
||||||
|
|
||||||
|
self.blocks = blocks
|
||||||
|
self.add(blocks)
|
||||||
|
|
||||||
|
def add_arrows(self):
|
||||||
|
self.arrows = VGroup()
|
||||||
|
for block in self.blocks:
|
||||||
|
arrow = Arrow(LEFT, RIGHT)
|
||||||
|
arrow.next_to(block)
|
||||||
|
label = TextMobject("SHA256")
|
||||||
|
label.scale(0.7)
|
||||||
|
label.next_to(arrow, UP, buff = SMALL_BUFF)
|
||||||
|
self.add(arrow, label)
|
||||||
|
block.arrow = arrow
|
||||||
|
self.arrows.add(VGroup(arrow, label))
|
||||||
|
|
||||||
|
def make_guesses(self):
|
||||||
|
for x in range(self.n_guesses):
|
||||||
|
e = self.n_nonce_digits
|
||||||
|
nonces = VGroup()
|
||||||
|
digests = VGroup()
|
||||||
|
for block in self.blocks:
|
||||||
|
nonce = Integer(random.randint(10**e, 10**(e+1)))
|
||||||
|
nonce.scale_to_fit_height(0.2)
|
||||||
|
nonce.next_to(block.get_bottom(), UP, SMALL_BUFF)
|
||||||
|
nonces.add(nonce)
|
||||||
|
digest = sha256_tex_mob(str(x) + str(block))
|
||||||
|
digest.scale_to_fit_height(block.get_height())
|
||||||
|
digest.next_to(block.arrow, RIGHT)
|
||||||
|
digests.add(digest)
|
||||||
|
self.add(nonces, digests)
|
||||||
|
self.dither(1./20)
|
||||||
|
self.remove(nonces, digests)
|
||||||
|
self.add(nonces, digests)
|
||||||
|
|
||||||
|
winner_index = 1
|
||||||
|
winner = self.miners[winner_index]
|
||||||
|
losers = VGroup(*filter(
|
||||||
|
lambda m : m is not winner,
|
||||||
|
self.miners
|
||||||
|
))
|
||||||
|
|
||||||
|
nonces[winner_index].highlight(GREEN)
|
||||||
|
new_digest = sha256_tex_mob("Winner", 60)
|
||||||
|
VGroup(*new_digest[:60]).highlight(YELLOW)
|
||||||
|
old_digest = digests[winner_index]
|
||||||
|
new_digest.replace(old_digest)
|
||||||
|
Transform(old_digest, new_digest).update(1)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
winner.change, "hooray",
|
||||||
|
*[
|
||||||
|
ApplyMethod(VGroup(
|
||||||
|
self.blocks[i], self.arrows[i],
|
||||||
|
nonces[i], digests[i]
|
||||||
|
).fade, 0.7)
|
||||||
|
for i in range(len(self.blocks))
|
||||||
|
if i is not winner_index
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.play(*[
|
||||||
|
ApplyMethod(loser.change, "angry", winner)
|
||||||
|
for loser in losers
|
||||||
|
])
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
#####
|
||||||
|
|
||||||
|
def get_payments(self, miner):
|
||||||
|
if not hasattr(self, "ledger"):
|
||||||
|
self.get_ledger() ##Unused
|
||||||
|
self.ledger.content.remove(*self.ledger.content[1:])
|
||||||
|
|
||||||
|
lines = VGroup()
|
||||||
|
|
||||||
|
miner_name = miner.label.get_tex_string()
|
||||||
|
top_line = TextMobject(miner_name, "gets", "10 LD")
|
||||||
|
top_line.highlight_by_tex(miner_name, LIGHT_GREY)
|
||||||
|
top_line.highlight_by_tex("LD", YELLOW)
|
||||||
|
lines.add(top_line)
|
||||||
|
payments = [
|
||||||
|
("Alice", "Bob", 20),
|
||||||
|
("Charlie", "You", 50),
|
||||||
|
]
|
||||||
|
for payment in payments:
|
||||||
|
lines.add(self.add_payment_line_to_ledger(*payment))
|
||||||
|
lines.add(TexMobject("\\vdots"))
|
||||||
|
for line in lines:
|
||||||
|
line.scale_to_fit_height(0.5)
|
||||||
|
lines.arrange_submobjects(
|
||||||
|
DOWN, buff = SMALL_BUFF, aligned_edge = LEFT
|
||||||
|
)
|
||||||
|
lines[-1].next_to(lines[-2], DOWN, buff = SMALL_BUFF)
|
||||||
|
return lines
|
||||||
|
|
||||||
|
class TwoBlockChains(DistributedBlockChainScene):
|
||||||
|
CONFIG = {
|
||||||
|
"n_blocks" : 4,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.defer_to_longer()
|
||||||
|
self.break_tie()
|
||||||
|
|
||||||
|
def defer_to_longer(self):
|
||||||
|
randy = self.randy
|
||||||
|
block_chains = VGroup()
|
||||||
|
block_chains.add(self.get_block_chain())
|
||||||
|
self.n_blocks += 1
|
||||||
|
block_chains.add(self.get_block_chain())
|
||||||
|
block_chains.scale(1.5)
|
||||||
|
|
||||||
|
block_chains[0].next_to(randy, UP+LEFT)
|
||||||
|
block_chains[1].next_to(randy, UP+RIGHT)
|
||||||
|
for block_chain in block_chains:
|
||||||
|
block_chain.shift_onto_screen()
|
||||||
|
|
||||||
|
conflicting = TextMobject("Conflicting")
|
||||||
|
conflicting.to_edge(UP)
|
||||||
|
conflicting.highlight(RED)
|
||||||
|
arrows = VGroup(*[
|
||||||
|
Arrow(
|
||||||
|
conflicting.get_bottom(), block_chain.get_top(),
|
||||||
|
color = RED,
|
||||||
|
buff = MED_LARGE_BUFF
|
||||||
|
)
|
||||||
|
for block_chain in block_chains
|
||||||
|
])
|
||||||
|
|
||||||
|
longer_chain_rect = SurroundingRectangle(block_chains[1])
|
||||||
|
longer_chain_rect.set_stroke(GREEN, 8)
|
||||||
|
checkmark = TexMobject("\\checkmark")
|
||||||
|
checkmark.highlight(GREEN)
|
||||||
|
checkmark.next_to(longer_chain_rect, UP)
|
||||||
|
checkmark.shift(RIGHT)
|
||||||
|
|
||||||
|
self.add(randy)
|
||||||
|
for side, chain in zip(["left", "right"], block_chains):
|
||||||
|
self.play(
|
||||||
|
randy.change, "raise_%s_hand"%side, chain,
|
||||||
|
LaggedStart(FadeIn, chain.blocks),
|
||||||
|
LaggedStart(FadeIn, chain.arrows),
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
Write(conflicting),
|
||||||
|
*map(ShowCreation, arrows)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(ShowCreation(longer_chain_rect))
|
||||||
|
self.play(Write(checkmark, run_time = 1))
|
||||||
|
self.play(randy.change, "thinking", checkmark)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
self.to_fade = VGroup(
|
||||||
|
conflicting, arrows,
|
||||||
|
longer_chain_rect, checkmark
|
||||||
|
)
|
||||||
|
self.block_chains = block_chains
|
||||||
|
|
||||||
|
def break_tie(self):
|
||||||
|
to_fade = self.to_fade
|
||||||
|
block_chains = self.block_chains
|
||||||
|
randy = self.randy
|
||||||
|
|
||||||
|
arrow = block_chains[1].arrows[-1]
|
||||||
|
block = block_chains[1].blocks[-1]
|
||||||
|
arrow_block = VGroup(arrow, block).copy()
|
||||||
|
|
||||||
|
block_chains.generate_target()
|
||||||
|
block_chains.target.arrange_submobjects(
|
||||||
|
DOWN, buff = MED_LARGE_BUFF, aligned_edge = LEFT
|
||||||
|
)
|
||||||
|
block_chains.target.next_to(randy, UP)
|
||||||
|
block_chains.target.to_edge(LEFT)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
MoveToTarget(block_chains),
|
||||||
|
FadeOut(to_fade),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
arrow_block.next_to(block_chains[0], RIGHT, buff = 0)
|
||||||
|
block_chains[0].add(arrow_block)
|
||||||
|
self.play(
|
||||||
|
randy.change, "confused", block_chains,
|
||||||
|
FadeIn(arrow_block),
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
arrow_block = arrow_block.copy()
|
||||||
|
arrow_block.next_to(SPACE_WIDTH*RIGHT, RIGHT)
|
||||||
|
self.play(
|
||||||
|
ApplyMethod(
|
||||||
|
arrow_block.next_to, block_chains[0], RIGHT, 0,
|
||||||
|
run_time = 3,
|
||||||
|
rate_func = squish_rate_func(smooth, 0.3, 0.8)
|
||||||
|
),
|
||||||
|
Broadcast(arrow_block),
|
||||||
|
)
|
||||||
|
block_chains[0].add(arrow_block)
|
||||||
|
rect = SurroundingRectangle(block_chains[0])
|
||||||
|
rect.set_stroke(GREEN, 8)
|
||||||
|
checkmark = TexMobject("\\checkmark")
|
||||||
|
checkmark.next_to(rect, UP)
|
||||||
|
checkmark.highlight(GREEN)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
ShowCreation(rect),
|
||||||
|
Write(checkmark),
|
||||||
|
randy.change, "happy", arrow_block
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
|
||||||
|
####
|
||||||
|
|
||||||
|
def create_pi_creatures(self):
|
||||||
|
randy = Randolph()
|
||||||
|
randy.to_edge(DOWN)
|
||||||
|
self.randy = randy
|
||||||
|
return VGroup(randy)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MinersInLiterature(ExternallyAnimatedScene):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class MiningIsALottery(Scene):
|
|
||||||
def construct(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue