Esempio n. 1
0
 def on_receive(self, obj, reprocess=False):
     if obj.hash in self.processed and not reprocess:
         return
     if random.random() > self.reliability:
         return
     self.processed[obj.hash] = True
     self.log("Processing %s %s" %
              ("block" if isinstance(obj, BeaconBlock) else "sig",
               to_hex(obj.hash[:4])),
              lvl=1)
     if isinstance(obj, BeaconBlock):
         return self.on_receive_beacon_block(obj)
     elif isinstance(obj, MainChainBlock):
         return self.on_receive_main_block(obj)
     elif isinstance(obj, ShardCollation):
         return self.on_receive_shard_collation(obj)
     elif isinstance(obj, Sig):
         return self.on_receive_sig(obj)
     elif isinstance(obj, BlockMakingRequest):
         if self.beacon_chain[-1] == obj.parent:
             mc_ref = self.blocks[obj.parent]
             for i in range(2):
                 if mc_ref.number == 0:
                     break
                 #mc_ref = self.blocks[mc_ref].parent_hash
             x = BeaconBlock(
                 self.blocks[obj.parent], self.id, self.ts,
                 self.sigs[obj.parent] if obj.parent in self.sigs else [],
                 self.blocks[self.main_chain[-1]], self.nb_notaries,
                 self.nb_shards)
             self.log("Broadcasting block %s" % to_hex(x.hash[:4]), lvl=1)
             self.broadcast(x)
             self.on_receive(x)
Esempio n. 2
0
 def on_receive_main_block(self, block):
     # Parent not yet received
     if block.parent_hash not in self.blocks:
         self.add_to_multiset(self.parentqueue, block.parent_hash, block)
         return None
     self.log("Processing main chain block %s" % to_hex(block.hash[:4]),
              lvl=1)
     self.blocks[block.hash] = block
     # Reorg the main chain if new head
     if block.number > self.blocks[self.main_chain[-1]].number:
         reorging = (block.parent_hash != self.main_chain[-1])
         self.change_head(self.main_chain, block)
         if reorging:
             self.recalculate_head(
                 self.beacon_chain, lambda b: isinstance(b, BeaconBlock) and
                 b.main_chain_ref in self.main_chain)
             for i in range(self.nb_shards):
                 self.recalculate_head(
                     self.shard_chains[i],
                     lambda b: isinstance(b, ShardCollation) and b.shard_id
                     == i and b.beacon_ref in self.beacon_chain)
     # Add child record
     self.add_to_multiset(self.children, block.parent_hash, block.hash)
     # Final steps
     self.process_children(block.hash)
     self.broadcast(block)
Esempio n. 3
0
 def broadcast(self, obj):
     self.log("Broadcasting %s %s" %
              ("block" if isinstance(obj, BeaconBlock) else "sig",
               to_hex(obj.hash[:4])),
              lvl=3)
     #self.network.broadcast(self, x)
     for p in self.network.peers[self.id]:
         recv_time = self.network.time + self.network.latency_distribution_sample(
         )
         if recv_time not in self.network.objqueue:
             self.network.objqueue[recv_time] = []
         self.network.objqueue[recv_time].append((p, obj))
Esempio n. 4
0
 def send(self, p, obj):
     #global commChannel
     #msg = [self.id, p.id, obj]
     #commChannel.append(msg)
     if isinstance(obj, BeaconBlock):
         object_type = "Beacon block"
     elif isinstance(obj, MainChainBlock):
         object_type = "Main chain block"
     elif isinstance(obj, ShardCollation):
         object_type = "Shard Collation"
     elif isinstance(obj, Sig):
         object_type = "Signature"
     elif isinstance(obj, BlockMakingRequest):
         object_type = "Block request"
     #print str(obj)
     req = self.comm.isend(obj, dest=p, tag=self.tag)
     self.log("%s %s sent from %d to %d"  % (object_type, to_hex(obj.hash[:4]), self.id, p))
     return req
Esempio n. 5
0
 def on_receive_beacon_block(self, block):
     # Parent not yet received
     if block.parent_hash not in self.blocks:
         self.add_to_multiset(self.parentqueue, block.parent_hash, block)
         return
     # Main chain parent not yet received
     if block.main_chain_ref not in self.blocks:
         self.add_to_multiset(self.parentqueue, block.main_chain_ref, block)
         return
     # Too early
     if block.ts > self.ts:
         self.add_to_timequeue(block)
         return
     # Check consistency of cross-link reference
     assert self.is_descendant(
         self.blocks[block.parent_hash].main_chain_ref,
         block.main_chain_ref)
     # Add the block
     self.log("Processing beacon block %s" % to_hex(block.hash[:4]), lvl=1)
     self.blocks[block.hash] = block
     # Am I a notary, and is the block building on the head? Then broadcast a signature.
     if block.parent_hash == self.beacon_chain[-1] or self.careless:
         if self.id in block.notaries:
             self.broadcast(Sig(self.id, block))
             self.on_receive(Sig(self.id, block))
     # Check for sigs, add to head?, make a block?
     if len(self.sigs.get(block.hash, [])) >= block.notary_req:
         if block.number > self.blocks[self.beacon_chain[
                 -1]].number and block.main_chain_ref in self.main_chain:
             self.change_beacon_head(block)
         if self.id in self.blocks[block.hash].child_proposers:
             my_index = self.blocks[block.hash].child_proposers.index(
                 self.id)
             target_ts = block.ts + self.base_ts_diff + my_index * self.skip_ts_diff
             self.add_to_timequeue(BlockMakingRequest(
                 block.hash, target_ts))
     # Add child record
     self.add_to_multiset(self.children, block.parent_hash, block.hash)
     # Final steps
     self.process_children(block.hash)
     self.broadcast(block)
Esempio n. 6
0
 def on_receive_shard_collation(self, block):
     # Parent not yet received
     if block.parent_hash not in self.blocks:
         self.add_to_multiset(self.parentqueue, block.parent_hash, block)
         return None
     # Beacon ref not yet received
     if block.beacon_ref not in self.blocks:
         self.add_to_multiset(self.parentqueue, block.beacon_ref, block)
         return None
     # Check consistency of cross-link reference
     assert self.is_descendant(self.blocks[block.parent_hash].beacon_ref, block.beacon_ref)
     self.log("Processing shard collation %s" % to_hex(block.hash[:4]))
     self.blocks[block.hash] = block
     # Set head if needed
     if block.number > self.blocks[self.shard_chains[block.shard_id][-1]].number and block.beacon_ref in self.beacon_chain:
         self.change_head(self.shard_chains[block.shard_id], block)
     # Add child record
     self.add_to_multiset(self.children, block.parent_hash, block.hash)
     # Final steps
     self.process_children(block.hash)
     self.broadcast(block)
Esempio n. 7
0
 def print_sig_digest(self):
     for sig_hash in self.sigs:
         print("%s : %s" % (to_hex(sig_hash[:4]), str(len(self.sigs[sig_hash]))))
Esempio n. 8
0
 def print_chain_digest(self):
     for block_hash in self.blocks:
         print("%s : %s" % (to_hex(block_hash[:4]), str(self.blocks[block_hash])))
Esempio n. 9
0
 def add_to_multiset(self, set, k, v):
     if k not in set:
         set[k] = []
     set[k].append(v)
     self.log("Adding %s to multiset" % to_hex(k[:4]))
Esempio n. 10
0
 def __str__(self):
     sti = " <MB Number : " + str(self.number)
     sti += ", hash : " + to_hex(self.hash[:4])
     sti += ", parent : " + to_hex(self.parent_hash[:4]) + "> "
     return sti