VariableProofOfWork in crypto

This commit is contained in:
Grant Sanderson 2017-07-05 10:14:46 -07:00
parent 9edccb116e
commit 1951457b89
2 changed files with 334 additions and 14 deletions

347
crypto.py
View file

@ -159,11 +159,11 @@ class AskQuestion(Scene):
self.dither(self.time_per_char*n_spaces)
self.dither(2)
class BitcoinPaperHighlightTitle(ExternallyAnimatedScene):
pass
# class BitcoinPaperHighlightTitle(ExternallyAnimatedScene):
# pass
class TimeBitcoinCover(ExternallyAnimatedScene):
pass
# class TimeBitcoinCover(ExternallyAnimatedScene):
# pass
class ListOfAttributes(Scene):
def construct(self):
@ -217,14 +217,85 @@ class UnknownAuthor(Scene):
)
self.dither()
class NameCryptoCurrencies(TeacherStudentsScene):
class DisectQuestion(TeacherStudentsScene):
def construct(self):
words = TextMobject("It's called a", "``cryptocurrency''")
words.highlight_by_tex("cryptocurrency", YELLOW)
self.teacher_says(words)
self.hold_up_question()
self.list_topics()
self.isolate_you()
def hold_up_question(self):
question = TextMobject(
"What does it mean to", "have", "a", "Bitcoin?"
)
question.highlight_by_tex("have", YELLOW)
question.next_to(self.teacher, UP)
question.to_edge(RIGHT, buff = LARGE_BUFF)
question.save_state()
question.shift(DOWN)
question.set_fill(opacity = 0)
self.play(
self.teacher.change, "raise_right_hand",
question.restore
)
self.change_student_modes(*["pondering"]*3)
self.dither()
self.bitcoin_word = question.get_part_by_tex("Bitcoin")
def list_topics(self):
topics = TextMobject(
"Digital signatures, ",
"Proof of work, ",
"Cryptographic hash functions, \\dots"
)
topics.scale_to_fit_width(2*SPACE_WIDTH - LARGE_BUFF)
topics.to_edge(UP)
topics.highlight_by_tex("Digital", BLUE)
topics.highlight_by_tex("Proof", GREEN)
topics.highlight_by_tex("hash", YELLOW)
for word in topics:
anims = [Write(word, run_time = 1)]
self.change_student_modes(
*["confused"]*3,
added_anims = anims,
look_at_arg = word
)
def isolate_you(self):
self.pi_creatures = VGroup()
you = self.students[1]
rect = FullScreenFadeRectangle()
words = TextMobject("Invent your own")
arrow = Arrow(UP, DOWN)
arrow.next_to(you, UP)
words.next_to(arrow, UP)
self.play(FadeIn(rect), Animation(you))
self.play(
Write(words),
ShowCreation(arrow),
you.change, "erm", words
)
self.play(Blink(you))
self.dither()
class CryptocurrencyEquation(Scene):
def construct(self):
parts = TextMobject(
"Ledger",
"- Trust",
"+ Cryptography",
"= Cryptocurrency"
)
VGroup(*parts[-1][1:]).highlight(YELLOW)
parts.scale_to_fit_width(2*SPACE_WIDTH - LARGE_BUFF)
for part in parts:
self.play(FadeIn(part))
self.dither(2)
class CryptocurrencyMarketCaps(ExternallyAnimatedScene):
pass
@ -250,9 +321,6 @@ class Hype(TeacherStudentsScene):
)
self.dither(3)
class AskQuestionCopy(AskQuestion):
pass
class LedgerScene(PiCreatureScene):
CONFIG = {
"ledger_width" : 6,
@ -3800,7 +3868,6 @@ class AliceRacesOtherMiners(DoubleSpendingAttack):
ff_arrow.target[1].shift(dist*UP)
ff_arrow.target.points[-2:] += dist*UP
self.revert_to_original_skipping_status()
self.play(
Broadcast(block),
*[
@ -3837,8 +3904,9 @@ class AliceRacesOtherMiners(DoubleSpendingAttack):
"Alice", "Miners", "Miners"
]
self.revert_to_original_skipping_status()
for winner in winners:
self.dither(2)
self.dither()
if winner == "Alice":
block = self.fraud_block
prev_block = last_fraud_block
@ -3867,7 +3935,9 @@ class AliceRacesOtherMiners(DoubleSpendingAttack):
else:
last_valid_block = block_copy
anims.append(Broadcast(block, run_time = 2))
self.proofs_of_work.remove(block.proof_of_work)
self.play(*anims)
self.proofs_of_work.add(block.proof_of_work)
#####
@ -3907,6 +3977,257 @@ class AliceRacesOtherMiners(DoubleSpendingAttack):
result.scale_to_fit_width(0.8*block.get_width())
result.move_to(block)
return result
class WhenToTrustANewBlock(DistributedBlockChainScene):
def construct(self):
chain = self.block_chain = self.get_block_chain()
chain.scale(2)
chain.to_edge(LEFT)
self.add(chain)
words = map(TextMobject, [
"Don't trust yet",
"Still don't trust",
"...a little more...",
"Maybe trust",
"Probably safe",
"Alright, you're good."
])
colors = [RED, RED, YELLOW, YELLOW, GREEN, GREEN]
self.add_new_block()
arrow = Arrow(UP, DOWN, color = RED)
arrow.next_to(chain.blocks[-1], UP)
for word, color in zip(words, colors):
word.highlight(color)
word.next_to(arrow, UP)
word = words[0]
self.play(
FadeIn(word),
ShowCreation(arrow)
)
for new_word in words[1:]:
kwargs = {
"run_time" : 3,
"rate_func" : squish_rate_func(smooth, 0.7, 1)
}
self.add_new_block(
Transform(word, new_word, **kwargs),
ApplyMethod(
arrow.highlight, new_word.get_color(),
**kwargs
)
)
self.dither(2)
def get_block(self):
block = DistributedBlockChainScene.get_block(self)
tuples = [
("Prev hash", UP, BLUE),
("Proof of work", DOWN, GREEN),
]
for word, vect, color in tuples:
mob = TextMobject(word)
mob.highlight(color)
mob.scale_to_fit_height(0.07*block.get_height())
mob.next_to(
block.get_edge_center(vect), -vect,
buff = 0.06*block.get_height()
)
block.add(mob)
attr = word.lower().replace(" ", "_")
setattr(block, attr, mob)
transactions = TextMobject("$\\langle$Transactions$\\rangle$")
transactions.scale_to_fit_width(0.8*block.get_width())
transactions.move_to(block)
block.add(transactions)
return block
def add_new_block(self, *added_anims):
blocks = self.block_chain.blocks
arrows = self.block_chain.arrows
block = blocks[-1].copy()
arrow = arrows[-1].copy()
VGroup(block, arrow).next_to(blocks[-1], RIGHT, buff = 0)
corner = SPACE_WIDTH*RIGHT + SPACE_HEIGHT*UP
block.save_state()
block.next_to(corner, UP+RIGHT)
self.play(
Broadcast(block),
ApplyMethod(
block.restore,
run_time = 3,
rate_func = squish_rate_func(smooth, 0.3, 0.8),
),
ShowCreation(
arrow,
run_time = 3,
rate_func = squish_rate_func(smooth, 0.7, 1),
),
*added_anims
)
arrows.add(arrow)
blocks.add(block)
class VariableProofOfWork(WhenToTrustANewBlock):
CONFIG = {
"block_height" : 3,
"block_width" : 3,
"n_guesses" : 60,
"n_proof_of_work_digits" : 11,
"n_miners" : 6,
}
def construct(self):
self.add_miner_and_hash()
self.change_requirement()
self.add_more_miners()
def add_miner_and_hash(self):
miner = PiCreature(color = GREY)
miner.scale(0.7)
miner.to_edge(LEFT)
block = self.get_block()
block.next_to(miner, RIGHT)
old_proof_of_work = block.proof_of_work
proof_of_work = self.get_rand_int_mob()
proof_of_work.replace(old_proof_of_work, dim_to_match = 1)
block.remove(old_proof_of_work)
block.add(proof_of_work)
block.proof_of_work = proof_of_work
arrow = Arrow(LEFT, RIGHT)
arrow.next_to(block)
sha_tex = TextMobject("SHA256")
sha_tex.scale(0.7)
sha_tex.next_to(arrow, UP, SMALL_BUFF)
sha_tex.highlight(YELLOW)
arrow.add(sha_tex)
digest = sha256_tex_mob("Random")
digest.next_to(arrow.get_end(), RIGHT)
miner.change("pondering", digest)
self.add(miner, block, arrow, digest)
for x in range(self.n_guesses):
new_pow = self.get_rand_int_mob()
new_pow.replace(proof_of_work, dim_to_match = 1)
Transform(proof_of_work, new_pow).update(1)
if x == self.n_guesses-1:
n_zeros = 60
else:
n_zeros = 0
new_digest = sha256_tex_mob(str(x+1), n_zeros)
new_digest.replace(digest)
Transform(digest, new_digest).update(1)
self.dither(1./20)
proof_of_work.highlight(GREEN)
VGroup(*digest[:60]).highlight(YELLOW)
self.miner = miner
self.block = block
self.arrow = arrow
self.digest = digest
def change_requirement(self):
digest = self.digest
requirement = TextMobject(
"Must start with \\\\",
"60", "zeros"
)
requirement.next_to(digest, UP, MED_LARGE_BUFF)
self.n_zeros_mob = requirement.get_part_by_tex("60")
self.n_zeros_mob.highlight(YELLOW)
self.play(Write(requirement, run_time = 2))
self.dither(2)
for n_zeros in 30, 32, 35, 37, 42:
self.change_challenge(n_zeros)
self.dither()
def add_more_miners(self):
miner = self.miner
block = self.block
miner_block = VGroup(miner, block)
target = miner_block.copy()
target[1].scale(
0.5, about_point = miner.get_right()
)
copies = VGroup(*[
target.copy()
for x in range(self.n_miners - 1)
])
everyone = VGroup(target, *copies)
everyone.arrange_submobjects(DOWN)
everyone.scale_to_fit_height(2*SPACE_HEIGHT - LARGE_BUFF)
everyone.to_corner(UP+LEFT)
self.play(Transform(miner_block, target))
self.play(LaggedStart(FadeIn, copies))
self.change_challenge(72)
self.dither(2)
###
def change_challenge(self, n_zeros):
digest = self.digest
proof_of_work = self.block.proof_of_work
n_zeros_mob = self.n_zeros_mob
new_digest = sha256_tex_mob(str(n_zeros), n_zeros)
new_digest.move_to(digest)
VGroup(*new_digest[:n_zeros]).highlight(YELLOW)
new_n_zeros_mob = TexMobject(str(n_zeros))
new_n_zeros_mob.move_to(n_zeros_mob)
new_n_zeros_mob.highlight(n_zeros_mob.get_color())
new_pow = self.get_rand_int_mob()
new_pow.replace(proof_of_work, dim_to_match = 1)
new_pow.highlight(proof_of_work.get_color())
self.play(
Transform(n_zeros_mob, new_n_zeros_mob),
Transform(
digest, new_digest,
submobject_mode = "lagged_start"
),
Transform(proof_of_work, new_pow),
)
def get_rand_int_mob(self):
e = self.n_proof_of_work_digits
return Integer(random.randint(10**e, 10**(e+1)))
class CompareBLockTimes(Scene):
def construct(self):
pass

View file

@ -125,7 +125,6 @@ class Mobject(object):
mob.points += total_vector
return self
def scale(self, scale_factor, about_point = None):
if about_point is not None:
self.shift(-about_point)