def test_receive_paxos_message_try(self): # try message try_msg = PaxosMessage('TRY', 1) try_msg.last_committed_block = GENESIS.block_id b = Block(1, GENESIS.block_id, ['a'], 1) b.depth = 1 try_msg.new_block = b.block_id self.node.respond = MagicMock() self.node.blocktree.nodes.update({b.block_id: b}) self.node.receive_paxos_message(try_msg, 1) assert self.node.respond.called assert self.node.s_max_block_depth == b.depth
def test_receive_paxos_message_propose(self): propose = PaxosMessage('PROPOSE', 1) b = Block(1, GENESIS.block_id, ['a'], 1) b.depth = 1 propose.new_block = GENESIS.block_id propose.com_block = GENESIS.block_id self.node.respond = MagicMock() self.node.receive_paxos_message(propose, 1) assert self.node.respond.called assert self.node.s_prop_block.block_id == propose.com_block assert self.node.s_supp_block.block_id == propose.new_block
def test_receive_paxos_message_try_ok_1(self): # try_ok message with no prop/supp block stored locally and message does not contain a propose block try_ok = PaxosMessage('TRY_OK', 1) b = Block(1, GENESIS.block_id, ['a'], 1) b.depth = 1 self.node.c_request_seq = 1 self.node.c_new_block = b self.node.c_votes = 5 self.node.broadcast = MagicMock() self.node.receive_paxos_message(try_ok, None) self.node.blocktree.nodes.update({b.block_id: b}) assert self.node.broadcast.called assert self.node.c_com_block == self.node.c_new_block
def create_block(self): """Create a block containing `new_txs` and return it. Returns: Block: The block that was created. """ logger.debug('create a block') # store depth of current head_block (will be parent of new block) d = self.blocktree.head_block.depth # create block self.blocktree.counter += 1 if len(self.new_txs) < MAX_TXN_COUNT: b = Block(self.id, self.blocktree.head_block.block_id, self.new_txs, self.blocktree.counter) # create a new, empty list (do not use clear!) self.new_txs = [] else: logger.debug( 'Cannot fit all transactions in the block that is beeing created. Remaining transactions ' 'will be included in the next block.') txns_include = self.new_txs[:MAX_TXN_COUNT] b = Block(self.id, self.blocktree.head_block.block_id, txns_include, self.blocktree.counter) self.new_txs = self.new_txs[MAX_TXN_COUNT:] self.readjust_timeout() # compute its depth (will be fixed -> depth field is only set once) b.depth = d + len(b.txs) self.blocktree.db.put(b'counter', str(self.blocktree.counter).encode()) # add block to blocktree self.blocktree.add_block(b) # promote node if self.state != QUICK: self.state = max(QUICK, self.state - 1) logger.debug('Got promoted. State = %s', str(self.state)) # add state of creator node to block b.creator_state = self.state logger.debug('created block with block id = %s', str(b.block_id)) return b
def test_receive_paxos_message_propose_ack(self): propose_ack = PaxosMessage('PROPOSE_ACK', 1) b = Block(1, GENESIS.block_id, ['a'], 1) b.depth = 1 propose_ack.com_block = b.block_id self.node.c_request_seq = 1 self.node.c_votes = 5 self.node.blocktree.nodes.update({b.block_id: b}) self.node.broadcast = MagicMock() self.node.commit = MagicMock() self.node.receive_paxos_message(propose_ack, None) assert self.node.broadcast.called obj = self.node.broadcast.call_args[0][0] assert obj.com_block == propose_ack.com_block
from piChain.PaxosNetwork import ConnectionManager from piChain.blocktree import Blocktree from piChain.messages import PaxosMessage, Block, RequestBlockMessage, RespondBlockMessage, Transaction, \ AckCommitMessage from piChain.config import ACCUMULATION_TIME, MAX_COMMIT_TIME, MAX_TXN_COUNT, TESTING, RECOVERY_BLOCKS_COUNT # variables representing the state of a node QUICK = 0 MEDIUM = 1 SLOW = 2 EPSILON = 0.001 # genesis block GENESIS = Block(-1, None, [], 0) GENESIS.depth = 0 logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) if not TESTING: logging.disable(logging.DEBUG) class Node(ConnectionManager): """This class represents a piChain node. It is a subclass of the ConnectionManager class defined in the networking module. This allows to directly call functions like broadcast and respond from the networking module and to override the receive-methods which are called in the networking module based on the type of the message. Args: node_index (int): the index of this node into the peers dictionary. The entry defines its ip address and port. peers_dict (dict): a dict containing the (ip, port) pairs for all nodes (see examples folder for its structure).