| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import json
- import time
- from ouroboros.utils import encode_genesis_data, decode_gensis_data, state_hash
- from ouroboros.consts import *
- from ouroboros.logger import Logger
- '''
- single block B_i for slot i in the system live time L,
- assigned to stakeholder U_j, with propability P_j_i,
- in the chain C, should be signed by U_j keys.
- '''
- class Block(object):
- '''
- @param previous_block: parent block to the current block
- @param data: is the transaction, or contracts in the leadger, or gensis block data,
- data is expected to be binary, no format is enforced
- @param slot_uid: the block corresponding slot monotonically increasing index,
- it's one-based
- @param gensis: boolean, True for gensis block
- '''
- def __init__(self, previous_block, data, slot_uid, genesis_time=time.time(), genesis=False):
- # state is hte hash of the previous block in the blockchain
- self.state=''
- if slot_uid>1:
- self.state=state_hash(previous_block)
- self.tx = data
- self.sl = slot_uid
- self.is_genesis=genesis
- self.endorsed=False
- self.log = Logger(genesis_time)
- self.leader_id=None
- self.endorser_id=None
- def __repr__(self):
- if self.is_genesis:
- return "GensisBlock at {slot:"+str(self.sl)+",data:"+str(self.tx)+",state:"+str(self.state)+"}\n"+str(self.tx)
- return "Block at {slot:"+str(self.sl)+",data:"+str(self.tx)+",state:"+str(self.state)+"}"
-
- def __hash__(self):
- if type(self.tx)==str:
- return hash((self.state, self.tx, self.sl))
- elif type(self.tx)==dict:
- return hash((self.state, self.tx[SEED], self.tx[TX]))
- else:
- return hash(str(self))
- def __eq__(self, block):
- return self.state==block.state and \
- self.tx == block.tx and \
- self.sl == block.sl
- def to_json(self):
- d = {'state':self.state, \
- 'data': self.tx, \
- 'sl': self.sl}
- return json.encoder(d)
- def set_endorsed(self):
- self.endorsed=True
- def set_endorser(self, id):
- self.endorser_id=id
- self.set_endorsed()
- def set_leader(self, id):
- self.leader_id=id
-
- @property
- def data(self):
- return self.tx
- @property
- def slot(self):
- return self.sl
- @property
- def empty(self):
- return (self.tx=='' or self.slot<0) and self.state==''
- def encode(self):
- return str(self).encode()
- class GensisBlock(Block):
- '''
- @param data: data is dictionary of list of (pk_i, s_i) public key,
- and stake respectively of the corresponding stakeholder U_i,
- seed of the leader election function.
- '''
- def __init__(self, previous_block, data, slot_uid, genesis_time=time.time()):
- # stakeholders is list of tuple (pk_i, s_i) for the ith stakeholder
- dist_block = data[0]
- self.stakeholders = dist_block[STAKEHOLDERS]
- self.distribution = dist_block[STAKEHOLDERS_DISTRIBUTIONS]
- self.seed = dist_block[SEED] #needed for pvss
- shd_buff = ''
- for shd in self.distribution:
- shd_buff +=str(shd)
- #data = encode_genesis_data(shd_buff)
- data_dict = {'seed':self.seed, 'distribution':shd_buff}
- Block.__init__(self, previous_block, str(data_dict), slot_uid, genesis_time, True)
- '''
- @return: the number of participating stakeholders in the blockchain
- '''
- @property
- def length(self):
- return len(self.stakeholders)
- def __getitem__(self, i):
- if i<0 or i>=self.length:
- raise "index is out of range!"
- return self.stakeholders[i]
- '''
- block lead by an adversary, or
- lead by offline leader
- is an empty Block
- '''
- class EmptyBlock(Block):
- def __init__(self, genesis_time=time.time()):
- Block.__init__(self, '', -1, genesis_time, False)
|