Beispiel #1
0
    def enter_any(self, prev_state):
        time.sleep(10)

        self.log.notice("Delegate connecting to other nodes ..")
        # Sub to other delegates
        for delegate_vk in VKBook.get_delegates():
            # Do not sub to ourself
            if delegate_vk == self.parent.verifying_key:
                continue

            self.parent.composer.add_sub(vk=delegate_vk, filter=delegate_delegate)

        # Sub to witnesses
        for witness_vk in VKBook.get_witnesses():
            self.parent.composer.add_sub(vk=witness_vk, filter=witness_delegate)

        # Pub on our own url
        self.parent.composer.add_pub(ip=self.parent.ip)

        # Add router socket
        self.parent.composer.add_router(ip=self.parent.ip)

        # Add dealer and sub socket for Masternodes
        for mn_vk in VKBook.get_masternodes():
            self.parent.composer.add_dealer(vk=mn_vk)
            self.parent.composer.add_sub(vk=mn_vk, filter=masternode_delegate)

        # Sleep for a bit while the daemon sets up these sockets TODO find a more reactive solution
        time.sleep(20)

        # Once done with boot state, transition to catchup
        self.parent.transition(DelegateCatchupState)
Beispiel #2
0
 def discover_network(self):
     self.ips = self.loop.run_until_complete(self.discover(self.mode))
     if len(self.ips) == 0: self.ips[self.host_ip] = int(time.time())
     mn_list = VKBook.get_masternodes()
     ip_list = list(self.ips.keys())
     if self.network.ironhouse.vk not in mn_list:
         if len(ip_list) == 1: return False
     return True
Beispiel #3
0
    def _fetch_tx_for_current_block(self):
        """
        Fetches the transactions for the current block being updated
        """
        assert self.current_block, "_fetch_tx_for_current_block called but self.current_block not set!"

        request = TransactionRequest.create(self.current_block.merkle_leaves)
        self.parent.composer.send_request_msg(message=request,
                                              vk=VKBook.get_masternodes()[0])
        self.current_request = request
Beispiel #4
0
    def validate_sig(self, sig: MerkleSignature) -> bool:
        assert self.merkle is not None, "Cannot validate signature without our merkle set"
        self.log.debugv("Validating signature: {}".format(sig))

        # Verify sender's vk exists in the state
        if sig.sender not in VKBook.get_delegates():
            self.log.warning("Received merkle sig from sender {} who was not registered nodes {}"
                             .format(sig.sender, VKBook.get_delegates()))
            return False

        # Verify we haven't received this signature already
        if sig in self.signatures:
            self.log.warning("Already received a signature from sender {}".format(sig.sender))
            return False

        # Below is just for debugging, so we can see if a signature cannot be verified
        if not sig.verify(self.merkle.root):
            self.log.warning("Delegate could not verify signature! Different Merkle trees.\nSig: {}".format(sig))

        return sig.verify(self.merkle.root)
Beispiel #5
0
    def enter(self, prev_state):

        # Sub to Masternodes
        for mn_vk in VKBook.get_masternodes():
            self.log.debug("Subscribes to MN with vk: {}".format(mn_vk))
            self.parent.composer.add_sub(filter=WITNESS_MASTERNODE_FILTER, vk=mn_vk, port=MN_TX_PUB_PORT)

        # Create publisher socket
        self.parent.composer.add_pub(ip=self.parent.ip)

        # Once done setting up sockets, transition to RunState
        self.parent.transition(WitnessRunState)
Beispiel #6
0
    def _check_ready(self):
        """
        Checks if the system is 'ready' (as described in the MNStagingState docstring). If all conditions are met,
        this function will transition to MNRunState.
        """
        # TODO for dev we require all delegates online. IRL a 2/3 majority should suffice
        # majority = VKBook.get_delegate_majority()
        majority = len(VKBook.get_delegates())

        num_ready = len(self.ready_delegates)

        if num_ready >= majority:
            self.log.important(
                "{}/{} Delegates are at the latest blockchain state! MN exiting StagingState."
                "\n(Ready Delegates = {})".format(num_ready,
                                                  len(VKBook.get_delegates()),
                                                  self.ready_delegates))
            self.parent.transition(MNRunState)
            return
        else:
            self.log.notice(
                "Only {} of {} required delegate majority ready. MN remaining in StagingState"
                .format(num_ready, majority))
Beispiel #7
0
    def enter_any(self, prev_state):
        # Add publisher socket for sending NewBlockNotifications to delegates
        self.parent.composer.add_pub(ip=self.parent.ip,
                                     port=MN_NEW_BLOCK_PUB_PORT)

        # Add router socket
        self.parent.composer.add_router(ip=self.parent.ip)

        # Add dealer sockets to TESTNET_DELEGATES, for purposes of requesting block data
        for vk in VKBook.get_delegates():
            self.parent.composer.add_dealer(vk=vk)

        # Once done booting, transition to staging
        self.parent.transition(MNStagingState)
Beispiel #8
0
    def check_majority(self):
        self.log.debug("delegate has {} signatures out of {} total TESTNET_DELEGATES"
                       .format(len(self.signatures), self.NUM_DELEGATES))

        if len(self.signatures) >= MAJORITY and not self.in_consensus:
            self.log.important("Delegate in consensus!")
            self.in_consensus = True

            # Create BlockContender and send it to all Masternode(s)
            bc = BlockContender.create(signatures=self.signatures, merkle_leaves=self.merkle.leaves_as_hex,
                                       prev_block_hash=self.parent.current_hash)
            for mn_vk in VKBook.get_masternodes():
                self.log.debug("Delegate sending block contender to masternode with VK {}".format(mn_vk))
                self.parent.composer.send_request_msg(message=bc, vk=mn_vk)
Beispiel #9
0
    def _request_update(self):
        """
        Makes a BlockMetaDataRequest to a Masternode. This gives the delegate the block meta data for all new blocks
        that this delegate needs to fetch
        """
        self.parent.current_hash = BlockStorageDriver.get_latest_block_hash()

        self.log.notice(
            "Requesting updates from Masternode with current block hash {}".
            format(self.parent.current_hash))
        request = BlockMetaDataRequest.create(
            current_block_hash=self.parent.current_hash)
        self.parent.composer.send_request_msg(message=request,
                                              vk=VKBook.get_masternodes()[0],
                                              timeout=BLOCK_REQ_TIMEOUT)
Beispiel #10
0
    def enter_any(self, prev_state):
        self.log.debug("MN IP: {}".format(self.parent.ip))

        # Add publisher socket
        self.parent.composer.add_pub(ip=self.parent.ip)

        # Add router socket
        self.parent.composer.add_router(ip=self.parent.ip)

        # Add dealer sockets to delegates, for purposes of requesting block data
        for vk in VKBook.get_delegates():
            self.parent.composer.add_dealer(vk=vk)

        # Once done booting, transition to run
        self.parent.transition(MNRunState)
Beispiel #11
0
    def check_majority(self):
        self.log.debug(
            "delegate has {} signatures out of {} total delegates".format(
                len(self.signatures), self.NUM_DELEGATES))

        if len(self.signatures) >= majority:
            self.log.important("Delegate in consensus!")
            self.in_consensus = True

            # DEBUG LINE -- todo remove later
            # self.log.notice("Delegate creating contender with merk leaves {}".format(self.merkle.leaves_as_hex))

            # Create BlockContender and send it to all Masternode(s)
            bc = BlockContender.create(signatures=self.signatures,
                                       merkle_leaves=self.merkle.leaves_as_hex)
            for mn_vk in VKBook.get_masternodes():
                self.parent.composer.send_request_msg(message=bc, vk=mn_vk)
Beispiel #12
0
 async def coro():
     node = None
     if vk in VKBook.get_all():
         try:
             node, cached = await asyncio.wait_for(
                 cls.dht.network.lookup_ip(vk), timeout)
         except:
             log.notice('Did not find an ip for VK {}'.format(vk))
     if node:
         cls.event_sock.send_json({
             'event': 'got_ip',
             'event_id': event_id,
             'public_key': node.public_key.decode(),
             'ip': node.ip,
             'vk': vk
         })
     else:
         cls.event_sock.send_json({
             'event': 'not_found',
             'event_id': event_id
         })
Beispiel #13
0
    def handle_blockmeta_request(self, request: BlockMetaDataRequest,
                                 envelope: Envelope):
        vk = envelope.seal.verifying_key
        assert vk in VKBook.get_delegates(
        ), "Got BlockMetaDataRequest from VK {} not in delegate VKBook!".format(
            vk)
        self.log.notice(
            "Masternode received BlockMetaDataRequest from delegate {}\n...request={}"
            .format(vk, request))

        # Get a list of block hashes up until this most recent block
        # TODO get_child_block_hashes return an error/assertion/something if block cannot be found
        child_hashes = BlockStorageDriver.get_child_block_hashes(
            request.current_block_hash)
        self.log.debugv(
            "Got descendant block hashes {} for block hash {}".format(
                child_hashes, request.current_block_hash))

        # If this hash could not be found or if it was the latest hash, no need to lookup any blocks
        if not child_hashes:
            self.log.debug(
                "Requested block hash {} is already up to date".format(
                    request.current_block_hash))
            reply = BlockMetaDataReply.create(block_metas=None)
            return reply

        # Build a BlockMetaData object for each descendant block
        block_metas = []
        for block_hash in child_hashes:
            block_data = BlockStorageDriver.get_block(hash=block_hash,
                                                      include_number=False)
            meta = BlockMetaData.create(**block_data)
            block_metas.append(meta)

        reply = BlockMetaDataReply.create(block_metas=block_metas)
        return reply
Beispiel #14
0
 def auth_validate(vk):
     return vk in VKBook.get_all()
Beispiel #15
0
 def validate(self):
     assert self.masternode_vk in VKBook.get_masternodes(), 'Not a masternode VK'