mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
[research/ouroboros] fixed evironment epoch/slot synchrony for one epoch only
This commit is contained in:
@@ -8,7 +8,7 @@ import math
|
||||
|
||||
class SynchedNTPClock(object):
|
||||
|
||||
def __init__(self, epoch_length, slot_length=120, ntp_server='europe.pool.ntp.org'):
|
||||
def __init__(self, epoch_length, slot_length=180, ntp_server='europe.pool.ntp.org'):
|
||||
#TODO how long should be the slot length
|
||||
self.epoch_length=epoch_length # how many slots in a a block
|
||||
self.slot_length=slot_length
|
||||
|
||||
@@ -57,68 +57,63 @@ class Z(object):
|
||||
self.current_slot = self.beacon.slot
|
||||
self.select_epoch_leaders()
|
||||
self.prev_leader_id=0
|
||||
self.signal()
|
||||
self.new_epoch_signal()
|
||||
#TODO need to assign the block from the last slot in the epoch
|
||||
while True:
|
||||
if not self.beacon.slot == self.current_slot:
|
||||
self.current_slot = self.beacon.slot
|
||||
self.signal()
|
||||
if self.beacon.epoch_slot != 0:
|
||||
self.new_slot_signal()
|
||||
else:
|
||||
self.new_epoch_signal()
|
||||
|
||||
def signal(self):
|
||||
########################
|
||||
#TODO fix cretical
|
||||
########################
|
||||
# run the state on a member, no static function for new_epoch, new_slot.
|
||||
def new_slot_signal(self):
|
||||
############
|
||||
# NEW SLOT #
|
||||
############
|
||||
y, pi = self.rands[self.current_slot]
|
||||
threads = []
|
||||
for sk in self.stakeholders:
|
||||
#TODO (fix) failed to synchronized current_slot 1234 for epoch length of 2 is two states
|
||||
# need to pass the slot with it's corresponding sigma, and proof
|
||||
thread = Thread(target=Stakeholder.new_slot, args=(sk, self.current_slot, y, pi))
|
||||
#sk.new_slot(self.current_slot, y, pi)
|
||||
threads.append(thread)
|
||||
thread.start()
|
||||
for th in threads:
|
||||
th.join()
|
||||
|
||||
if self.beacon.epoch_slot!=0:
|
||||
############
|
||||
# NEW SLOT #
|
||||
############
|
||||
y, pi = self.rands[self.current_slot]
|
||||
threads = []
|
||||
for sk in self.stakeholders:
|
||||
#TODO (fix) failed to synchronized current_slot 1234 for epoch length of 2 is two states
|
||||
# need to pass the slot with it's corresponding sigma, and proof
|
||||
thread = Thread(target=Stakeholder.new_slot, args=(sk, self.current_slot, y, pi))
|
||||
#sk.new_slot(self.current_slot, y, pi)
|
||||
threads.append(thread)
|
||||
thread.start()
|
||||
for th in threads:
|
||||
th.join()
|
||||
else:
|
||||
#############
|
||||
# NEW EPOCH #
|
||||
#############
|
||||
vrf = self.stakeholders[self.current_leader_id].vrf
|
||||
if self.beacon.epoch != self.current_epoch:
|
||||
self.current_epoch = self.beacon.epoch
|
||||
self.rands = self.beacon.next_epoch_seeds(vrf)
|
||||
self.select_epoch_leaders()
|
||||
for idx, sk in enumerate(self.stakeholders):
|
||||
if sk.id==id:
|
||||
self.prev_leader_id=idx
|
||||
self.cached_dist = self.get_epoch_distribution()
|
||||
for sk in self.stakeholders:
|
||||
sk.current_slot_uid=self.beacon.slot
|
||||
def new_epoch_signal(self):
|
||||
#############
|
||||
# NEW EPOCH #
|
||||
#############
|
||||
vrf = self.stakeholders[self.current_leader_id].vrf
|
||||
if self.beacon.epoch != self.current_epoch:
|
||||
self.current_epoch = self.beacon.epoch
|
||||
self.rands = self.beacon.next_epoch_seeds(vrf)
|
||||
self.select_epoch_leaders()
|
||||
for idx, sk in enumerate(self.stakeholders):
|
||||
if sk.id==id:
|
||||
self.prev_leader_id=idx
|
||||
self.cached_dist = self.get_epoch_distribution()
|
||||
for sk in self.stakeholders:
|
||||
sk.current_slot_uid=self.beacon.slot
|
||||
###
|
||||
genesis_item = self.get_genesis_data()
|
||||
data = Data()
|
||||
data.append(genesis_item)
|
||||
self.current_block=GensisBlock(self.current_block, data, self.beacon.slot, self.genesis_time)
|
||||
assert self.current_block is not None
|
||||
current_epoch=Epoch(self.current_block, self.epoch_length, self.epoch, self.genesis_time)
|
||||
threads = []
|
||||
for sk in self.stakeholders:
|
||||
#sk.new_epoch(current_epoch)
|
||||
thread = Thread(target=Stakeholder.new_epoch, args=(sk, current_epoch))
|
||||
threads.append(thread)
|
||||
thread.start()
|
||||
for th in threads:
|
||||
th.join()
|
||||
@property
|
||||
def endorser_len(self):
|
||||
#TODO (impl)
|
||||
pass
|
||||
genesis_item = self.get_genesis_data()
|
||||
data = Data()
|
||||
data.append(genesis_item)
|
||||
self.current_block=GensisBlock(self.current_block, data, self.beacon.slot, self.genesis_time)
|
||||
assert self.current_block is not None
|
||||
current_epoch=Epoch(self.current_block, self.epoch_length, self.epoch, self.genesis_time)
|
||||
threads = []
|
||||
for sk in self.stakeholders:
|
||||
#sk.new_epoch(current_epoch)
|
||||
thread = Thread(target=Stakeholder.new_epoch, args=(sk, current_epoch))
|
||||
threads.append(thread)
|
||||
thread.start()
|
||||
for th in threads:
|
||||
th.join()
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
buff= f"envirnment of {self.length} stakholders\tcurrent leader's id: {self.current_leader_id}\tepoch_slot: {self.epoch_slot}\tendorser_id: {self.current_endorser_id}"
|
||||
@@ -179,11 +174,32 @@ class Z(object):
|
||||
def current_endorser_id(self):
|
||||
return self.slot_committee[self.current_slot][1]
|
||||
|
||||
@property
|
||||
def current_endorser_uid(self):
|
||||
return self.stakeholders[self.current_endorser_id].id
|
||||
|
||||
@property
|
||||
def current_endorser(self):
|
||||
self.log.info(f"getting endorser of id: {self.current_leader_id}")
|
||||
return self.stakeholders[self.current_endorser_id]
|
||||
|
||||
@property
|
||||
def current_endorser_sig_pk(self):
|
||||
return self.stakeholders[self.current_endorser_id].sig_pk
|
||||
|
||||
def endorser(self, slot):
|
||||
return self.stakeholders[self.slot_committee[slot][1]]
|
||||
|
||||
def endorser_sig_pk(self, slot):
|
||||
return self.endorser(slot).sig_pk
|
||||
|
||||
def endorser_vrf_pk(self, slot):
|
||||
return self.endorser(slot).vrf_pk
|
||||
|
||||
def is_current_endorser(self, id):
|
||||
_, edr_idx = self.slot_committee[self.beacon.slot]
|
||||
return id == self.stakeholders[edr_idx].id
|
||||
|
||||
@property
|
||||
def current_leader_vrf_pk(self):
|
||||
return self.stakeholders[self.current_leader_id].vrf_pk
|
||||
@@ -192,6 +208,11 @@ class Z(object):
|
||||
def current_leader_vrf_g(self):
|
||||
return self.stakeholders[self.current_leader_id].vrf_base
|
||||
|
||||
def is_current_leader(self, id):
|
||||
ldr_idx, _ = self.slot_committee[self.beacon.current_slot]
|
||||
return id == self.stakeholders[ldr_idx].id
|
||||
|
||||
|
||||
'''
|
||||
@property
|
||||
def current_epoch_leader(self):
|
||||
@@ -209,25 +230,13 @@ class Z(object):
|
||||
def current_leader_sig_pk(self):
|
||||
return self.stakeholders[self.current_leader_id].sig_pk
|
||||
|
||||
@property
|
||||
def current_endorser_sig_pk(self):
|
||||
return self.stakeholders[self.current_endorser_id].sig_pk
|
||||
|
||||
def endorser(self, epoch_slot):
|
||||
assert epoch_slot >= 0 and epoch_slot < self.epoch_length
|
||||
return self.stakeholders[epoch_slot]
|
||||
|
||||
def endorser_sig_pk(self, epoch_slot):
|
||||
return self.endorser(epoch_slot).sig_pk
|
||||
|
||||
def endorser_vrf_pk(self, epoch_slot):
|
||||
return self.endorser(epoch_slot).vrf_pk
|
||||
|
||||
#note! assumes epoch_slot lays in the current epoch
|
||||
def leader(self, epoch_slot):
|
||||
assert epoch_slot >= 0 and epoch_slot < self.epoch_length
|
||||
return self.stakeholders[epoch_slot]
|
||||
def leader(self, slot):
|
||||
return self.stakeholders[self.slot_committee[slot][0]]
|
||||
|
||||
'''
|
||||
def leader_sig_pk(self, epoch_slot):
|
||||
return self.leader(epoch_slot).sig_pk
|
||||
|
||||
@@ -236,7 +245,7 @@ class Z(object):
|
||||
|
||||
def leader_vrf_g(self, epoch_slot):
|
||||
return self.leader(epoch_slot).vrf_base
|
||||
|
||||
'''
|
||||
def prev_leader_vrf_pk(self):
|
||||
return self.stakeholders[self.prev_leader_id].vrf_pk
|
||||
|
||||
@@ -315,8 +324,8 @@ class Z(object):
|
||||
# under a single condition that no one is able to predict who is next
|
||||
assert not leader_idx==endorser_idx
|
||||
#TODO move leader/endorser to a dictionary
|
||||
|
||||
self.slot_committee[slot_idx] = (leader_idx, endorser_idx)
|
||||
self.log.highlight(f'slot {slot_idx} has committee leader/endorser {leader_idx}/{endorser_idx}\nleader: {self.stakeholders[leader_idx]}\nendorser: {self.stakeholders[endorser_idx]}')
|
||||
self.epoch_initialized[str(self.epoch)] = True
|
||||
|
||||
def broadcast_block(self, cur_block, signed_block, slot_uid):
|
||||
@@ -332,13 +341,6 @@ class Z(object):
|
||||
self.print_blockchain()
|
||||
|
||||
|
||||
def is_current_leader(self, id):
|
||||
ldr_idx, _ = self.slot_committee[self.beacon.current_slot]
|
||||
return id == self.stakeholders[ldr_idx].id
|
||||
|
||||
def is_current_endorser(self, id):
|
||||
_, edr_idx = self.slot_committee[self.beacon.current_slot]
|
||||
return id == self.stakeholders[edr_idx].id
|
||||
|
||||
@property
|
||||
def block_id(self):
|
||||
@@ -348,7 +350,7 @@ class Z(object):
|
||||
#TODO commit this step to handshake phases
|
||||
self.current_blk_endorser_sig=None
|
||||
self.log.info(f"endorsing block for current_leader_id: {self.current_leader_id}")
|
||||
confirmed = self.stakeholders[self.current_leader_id].confirm_endorsing(sig, self.block_id, self.epoch_slot)
|
||||
confirmed = self.stakeholders[self.current_leader_id].confirm_endorsing(sig, self.block_id, self.current_slot)
|
||||
if confirmed:
|
||||
self.current_blk_endorser_sig=sig
|
||||
else:
|
||||
@@ -360,17 +362,18 @@ class Z(object):
|
||||
bc = sh.blockchain
|
||||
self.log.highlight(f"<blockchain> {len(bc)} blocks: "+str(bc))
|
||||
|
||||
'''
|
||||
def confirm_endorsing(self, sig, blk_uid):
|
||||
if blk_uid==self.current_slot:
|
||||
self.current_blk_endorser_sig = sig
|
||||
|
||||
'''
|
||||
def corrupt_leader(self):
|
||||
self.corrupt(self.current_leader_id)
|
||||
|
||||
def corrupt_endorse(self):
|
||||
def corrupt_endorser(self):
|
||||
self.corrupt(self.current_endorser_id)
|
||||
|
||||
def corrupt_blk(self):
|
||||
self.log.warn(f"<corrupt_blk> at slot: {self.current_slot}")
|
||||
self.corrupt_leader()
|
||||
self.corrupt_endorse()
|
||||
self.corrupt_endorser()
|
||||
@@ -57,11 +57,11 @@ class Stakeholder(object):
|
||||
def __repr__(self):
|
||||
buff=''
|
||||
if self.env.is_current_leader(self.id):
|
||||
buff = f"\tleader {self.id} with stake:{self.stake}\nsig_sk: {self.sig_pk}"
|
||||
buff = f"\tleader {self.id} with stake:{self.stake}\nsig_pk: {self.sig_pk}"
|
||||
elif self.env.is_current_endorser(self.id):
|
||||
buff = f"\tendorser {self.id} with stake:{self.stake}\nsig_sk: {self.sig_pk}"
|
||||
buff = f"\tendorser {self.id} with stake:{self.stake}\nsig_pk: {self.sig_pk}"
|
||||
else:
|
||||
buff = f"\thonest committee memeber {self.id} with stake:{self.stake}\nsig_sk: {self.sig_pk}"
|
||||
buff = f"\thonest committee memeber {self.id} with stake:{self.stake}\nsig_pk: {self.sig_pk}"
|
||||
return buff
|
||||
|
||||
def __call__(self, env):
|
||||
@@ -143,22 +143,30 @@ class Stakeholder(object):
|
||||
signed_block=None
|
||||
#TODO should wait for l slot until block is endorsed
|
||||
endorsing_cnt=10
|
||||
while not self.current_block.endorsed:
|
||||
#TODO (rev)
|
||||
while not self.current_block.endorsed or self.blockchain[self.current_slot_uid]:
|
||||
time.sleep(1)
|
||||
self.log.info("...waiting for endorsment..")
|
||||
endorsing_cnt-=1
|
||||
'''
|
||||
if not self.current_block.endorsed:
|
||||
self.log.warn("failure endorsing the block...")
|
||||
self.current_block = EmptyBlock(self.env.genesis_time)
|
||||
'''
|
||||
signed_block = sign_message(self.passwd, self.sig_sk, self.current_block)
|
||||
self.env.broadcast_block(self.current_block, signed_block, self.current_slot_uid)
|
||||
|
||||
@property
|
||||
def current_slot(self):
|
||||
return self.env.beacon.current_slot
|
||||
|
||||
'''
|
||||
only endorser can broadcast block
|
||||
'''
|
||||
def endorse_block(self):
|
||||
if not self.env.is_current_endorser(self.id):
|
||||
return
|
||||
assert self.env.is_current_endorser(self.id)
|
||||
assert self.env.endorser_sig_pk(self.env.beacon.slot) == self.sig_pk, f' assertion failed for beacon slot {self.env.beacon.slot}, current_slot {self.current_slot}, lhs: {self.env.endorser_sig_pk(self.env.beacon.slot)},\nrhs: {self.sig_pk}\nleader\endorser ids {self.env.slot_committee[self.env.beacon.slot][0]}/{self.env.slot_committee[self.env.beacon.slot][1]}'
|
||||
#assert self.env.endorser_sig_pk(self.current_slot) == self.sig_pk, f'lsh: {self.env.endorser_sig_pk(self.current_slot)},\nrhs: {self.sig_pk}'
|
||||
self.current_block.set_endorser(self.id)
|
||||
self.log.info(f"endorsing block for current_leader_id: {self.env.current_leader_id}")
|
||||
if not self.env.is_current_endorser(self.id):
|
||||
@@ -210,22 +218,26 @@ class Stakeholder(object):
|
||||
self.log.warn("block endorsing verification failed")
|
||||
self.env.corrupt_blk()
|
||||
|
||||
def confirm_endorsing(self, endorser_sig, blk_uid, epoch_slot):
|
||||
def confirm_endorsing(self, endorser_sig, blk_uid, slot):
|
||||
self.log.highlight(f"confirming block with epoch slot id {blk_uid}")
|
||||
confirmed = False
|
||||
cur_blk, _ = self.__get_blk(blk_uid)
|
||||
self.log.highlight(f'confirming endorsed block {str(cur_blk)}')
|
||||
self.log.highlight(f'confirming endorsed has slot_uid: {self.current_slot_uid}')
|
||||
self.log.highlight(f'confirming endorsed has slot: {slot} epoch slot_uid: {self.current_slot_uid}')
|
||||
self.log.highlight(f'confirming endorsed has sig_pk: {self.env.current_endorser_sig_pk}')
|
||||
if verify_signature(self.env.endorser_sig_pk(epoch_slot), cur_blk, endorser_sig):
|
||||
endorser_sig_pk = self.env.endorser_sig_pk(self.env.beacon.slot)
|
||||
self.log.highlight(f'confirming endorsed sig pk: {endorser_sig_pk}')
|
||||
if verify_signature(endorser_sig_pk, cur_blk, endorser_sig):
|
||||
if self.current_slot_uid==self.env.current_slot:
|
||||
self.current_block.set_endorser(self.current_endorser_id)
|
||||
self.log.highlight("set current block as endorsed")
|
||||
self.current_block.set_endorser(self.env.current_endorser_uid)
|
||||
self.current_block.set_endorsed()
|
||||
else:
|
||||
self.blockchain[blk_uid].set_endorser(self.current_endorser_id)
|
||||
self.log.highlight(f"set delayed blockchain block with uid: {blk_uid} as endorsed")
|
||||
self.blockchain[blk_uid].set_endorser(self.env.current_endorser_uid)
|
||||
self.blockchain[blk_uid].set_endorsed()
|
||||
confirmed=True
|
||||
else:
|
||||
self.log.warn(f"confirmed enderser signature failure for pk: {str(self.env.current_endorser_sig_pk)} on block {str(cur_blk)} of signature {str(endorser_sig)}")
|
||||
self.log.warn(f"confirmed enderser signature failure for pk: {str(endorser_sig_pk)} on block {str(cur_blk)} of signature {str(endorser_sig)}")
|
||||
confirmed=False
|
||||
return confirmed
|
||||
Reference in New Issue
Block a user