Beispiel #1
0
    def verify(self, transaction):
        try:
            decoded = DecodedTransaction.from_transaction(transaction, self.ABI)
        except ValueError as e:
            logger.error('Transaction verification failed: %s', str(e))
            return False

        logger.debug('Expected: %s, Actual: %s', self, decoded)
        guid, artifact_type, amount, artifact_uri, num_artifacts, duration, bloom, metadata = decoded.parameters

        bloom_value = 0
        for b in bloom:
            bloom_value = bloom_value << 256 | int(b)

        artifact_type = ArtifactType(int(artifact_type))
        artifact_uri = artifact_uri.decode('utf-8')

        return decoded.value == 0 and \
            artifact_type == self.artifact_type and \
            artifact_uri == self.artifact_uri and \
            num_artifacts == self.num_artifacts and \
            duration == self.duration and \
            bloom_value == self.bloom and \
            amount == self.amount and \
            metadata.decode('utf-8') == self.metadata
Beispiel #2
0
def bounty_to_dict(bounty):
    return {
        'guid': str(uuid.UUID(int=bounty[0])),
        'artifact_type': ArtifactType.to_string(ArtifactType(bounty[1])),
        'author': bounty[2],
        'amount': str(bounty[3]),
        'uri': bounty[4],
        'num_artifacts': bounty[5],
        'expiration': bounty[6],
        'assigned_arbiter': bounty[7],
        'quorum_reached': bounty[8],
        'quorum_reached_block': bounty[9],
        'quorum_mask': safe_int_to_bool_list(bounty[10], bounty[5]),
        'metadata': bounty[11]
    }
    def __post_init__(self):
        if not BountyMetadata.validate(self.metadata):
            raise ValueError

        if not ArtifactType(self.artifact_type):
            raise ValueError
    async def run_task(self, task_index):
        conn = aiohttp.TCPConnector(limit=0, limit_per_host=0)
        timeout = aiohttp.ClientTimeout(total=REQUEST_TIMEOUT)
        async with aiohttp.ClientSession(connector=conn, timeout=timeout) as session:
            redis = await aioredis.create_redis_pool(self.redis_uri)
            while not self.finished:
                try:
                    next_job = await redis.blpop(self.queue, timeout=1)
                    if next_job is None:
                        continue

                    _, job = next_job
                    job = json.loads(job.decode('utf-8'))
                    logger.info(f'Got job on task {task_index}', extra={'extra': job})

                    guid = job['guid']
                    uri = job['uri']

                    polyswarmd_uri = job['polyswarmd_uri']

                    if self.api_key and not polyswarmd_uri.startswith('https://'):
                        raise ApiKeyException()

                    index = job['index']
                    chain = job['chain']
                    metadata = job.get('metadata', None)

                    duration = job['duration']
                    timestamp = job['ts']
                    artifact_type = ArtifactType(int(job['artifact_type']))

                    if timestamp + duration <= time.time() // 1:
                        raise ExpiredException()

                except OSError:
                    logger.exception('Redis connection down')
                    continue
                except aioredis.errors.ReplyError:
                    logger.exception('Redis out of memory')
                    continue
                except KeyError as e:
                    logger.exception(f"Bad message format on task {task_index}: {e}")
                    continue
                except ExpiredException:
                    logger.exception(f'Received expired job {guid} index {index}')
                    continue
                except ApiKeyException:
                    logger.exception("Refusing to send API key over insecure transport")
                    continue
                except (AttributeError, TypeError, ValueError):
                    logger.exception('Invalid job received, ignoring')
                    continue

                headers = {'Authorization': self.api_key} if self.api_key is not None else None
                uri = f'{polyswarmd_uri}/artifacts/{uri}/{index}'
                async with self.download_lock:
                    try:
                        response = await session.get(uri, headers=headers)
                        response.raise_for_status()

                        content = await response.read()
                    except aiohttp.ClientResponseError:
                        logger.exception(f'Error fetching artifact {uri} on task {task_index}')
                        continue
                    except asyncio.TimeoutError:
                        logger.exception(f'Timeout fetching artifact {uri} on task {task_index}')
                        continue

                async with self.scan_lock:
                    result = await self.scanner.scan(guid, artifact_type, content, metadata, chain)

                j = json.dumps({
                    'index': index,
                    'bit': result.bit,
                    'verdict': result.verdict,
                    'confidence': result.confidence,
                    'metadata': result.metadata,
                })

                logger.info(f'Scan results on task {task_index}', extra={'extra': j})

                key = f'{self.queue}_{guid}_{chain}_results'
                try:
                    await redis.rpush(key, j)
                    self.tries = 0
                except OSError:
                    logger.exception('Redis connection down')
                except aioredis.errors.ReplyError:
                    logger.exception('Redis out of memory')
def test_url_artifact_type_from_int():
    # arrange
    # act
    artifact_type = ArtifactType(1)
    # assert
    assert artifact_type == ArtifactType.URL
def test_file_artifact_type_from_int():
    # arrange
    # act
    artifact_type = ArtifactType(0)
    # assert
    assert artifact_type == ArtifactType.FILE
Beispiel #7
0
class NewBounty(WebsocketFilterMessage[NewBountyMessageData]):
    """NewBounty

    doctest:
    When the doctest runs, MetadataHandler._substitute_metadata is already defined outside this
    doctest (in __main__.py). Running this as a doctest will not trigger network IO.

    >>> event = mkevent({
    ... 'guid': 1066,
    ... 'artifactType': 1,
    ... 'author': addr1,
    ... 'amount': 10,
    ... 'artifactURI': '912bnadf01295',
    ... 'expirationBlock': 118,
    ... 'metadata': 'ZWassertionuri'})
    >>> decoded_msg(NewBounty.serialize_message(event))
    {'block_number': 117,
     'data': {'amount': '10',
              'artifact_type': 'url',
              'author': '0x00000000000000000000000000000001',
              'expiration': '118',
              'guid': '00000000-0000-0000-0000-00000000042a',
              'metadata': [{'bounty_id': 69540800813340,
                            'extended_type': 'EICAR virus test files',
                            'filename': 'eicar_true',
                            'md5': '44d88612fea8a8f36de82e1278abb02f',
                            'mimetype': 'text/plain',
                            'sha1': '3395856ce81f2b7382dee72602f798b642f14140',
                            'sha256': '275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f',
                            'size': 68,
                            'type': 'FILE'}],
              'uri': '912bnadf01295'},
     'event': 'bounty',
     'txhash': '0000000000000000000000000000000b'}
    """
    event: ClassVar[str] = 'bounty'
    schema: ClassVar[PSJSONSchema] = PSJSONSchema({
        'properties': {
            'guid': guid,
            'artifact_type': {
                'type':
                'string',
                'enum': [
                    name.lower()
                    for name, value in ArtifactType.__members__.items()
                ],
                'srckey':
                lambda k, e: ArtifactType.to_string(
                    ArtifactType(e['artifactType']))
            },
            'author': ethereum_address,
            'amount': {
                'type': 'string',
            },
            'uri': {
                'srckey': 'artifactURI'
            },
            'expiration': {
                'srckey': 'expirationBlock',
                'type': 'string',
            },
            'metadata': {
                'type': 'string'
            }
        }
    })

    @classmethod
    def to_message(cls, event) -> WebsocketEventMessage[NewBountyMessageData]:
        return MetadataHandler.fetch(super().to_message(event),
                                     validate=BountyMetadata.validate)