Beispiel #1
0
    def create(self, api: ContractsApiLike, owner: Entity, fee: int):
        # Set contract owner (required for resource prefix)
        self.owner = owner

        if self._init is None:
            raise RuntimeError("Contract has no initialisation function")

        # Generate resource addresses used by persistent globals
        try:
            resource_addresses = [
                'fetch.contract.state.{}'.format(self.digest.to_hex())
            ]
            resource_addresses.extend(
                ShardMask.state_to_address(address, self)
                for address in self._parser.used_globals_to_addresses(
                    self._init, [self._owner]))
        except (UnparsableAddress, UseWildcardShardMask):
            logging.warning(
                "Couldn't auto-detect used shards, using wildcard shard mask")
            shard_mask = BitVector()
        else:
            # Generate shard mask from resource addresses
            shard_mask = ShardMask.resources_to_shard_mask(
                resource_addresses, api.server.num_lanes())

        return self._api(api).create(owner, self, fee, shard_mask=shard_mask)
Beispiel #2
0
    def _build_shard_mask(self, num_lanes: int, name: Optional[str],
                          arguments: List[Any]) -> BitVector:
        try:
            resource_addresses = [
                'fetch.contract.state.{}'.format(str(self.address)),
            ]

            # only process the init functions resources if this function is actually present
            if name is not None:
                variables = self._parser.used_globals_to_addresses(
                    name, arguments)
                for variable in variables:
                    resource_addresses.append(
                        ShardMask.state_to_address(str(self.address),
                                                   variable))

            shard_mask = ShardMask.resources_to_shard_mask(
                resource_addresses, num_lanes)

        except (UnparsableAddress, UseWildcardShardMask, EtchParserError,
                AssertionError) as ex:
            logging.debug('Parser Error: {}'.format(ex))
            logging.warning(
                "Couldn't auto-detect used shards, using wildcard shard mask")
            shard_mask = BitVector()

        return shard_mask
Beispiel #3
0
    def test_resource_to_shard(self):
        # Test known addresses
        addresses = ['abc', 'def', 'XYZ']
        shards = [2, 3, 1]

        for add, sh in zip(addresses, shards):
            self.assertEqual(ShardMask.resource_to_shard(add, 4), sh)

        # Repeat for different lane number, expect different results
        addresses = ['abc', 'def', 'XYZ']
        shards = [10, 11, 13]

        for add, sh in zip(addresses, shards):
            self.assertEqual(ShardMask.resource_to_shard(add, 16), sh)
    def test_state_to_address(self):
        contract = mock.Mock()
        contract.digest.to_hex.side_effect = ['abc']
        contract.owner = 'def'

        address = ShardMask.state_to_address('xyz', contract)
        self.assertEqual(address, 'abc.def.state.xyz')
    def test_resource_to_shard(self):
        # Test rejection of invalid lane number
        with self.assertRaises(AssertionError):
            ShardMask.resource_to_shard('abc', 3)

        # Test known addresses
        addresses = ['abc', 'def', 'XYZ']
        shards = [2, 3, 1]

        for add, sh in zip(addresses, shards):
            self.assertEqual(ShardMask.resource_to_shard(add, 4), sh)

        # Repeat for different lane number, expect different results
        addresses = ['abc', 'def', 'XYZ']
        shards = [10, 11, 13]

        for add, sh in zip(addresses, shards):
            self.assertEqual(ShardMask.resource_to_shard(add, 16), sh)
Beispiel #6
0
    def action(self, api: ContractsApiLike, name: str, fee: int,
               signers: List[Entity], *args):
        if self._owner is None:
            raise RuntimeError(
                'Contract has no owner, unable to perform any actions. Did you deploy it?'
            )

        if name not in self._actions:
            raise RuntimeError(
                '{} is not an valid action name. Valid options are: {}'.format(
                    name, ','.join(list(self._actions))))

        try:
            # Generate resource addresses used by persistent globals
            resource_addresses = [
                ShardMask.state_to_address(address, self)
                for address in self._parser.used_globals_to_addresses(
                    name, list(args))
            ]
        except (UnparsableAddress, UseWildcardShardMask):
            logging.warning(
                "Couldn't auto-detect used shards, using wildcard shard mask")
            shard_mask = BitVector()
        else:
            # Generate shard mask from resource addresses
            shard_mask = ShardMask.resources_to_shard_mask(
                resource_addresses, api.server.num_lanes())

        return self._api(api).action(self._digest,
                                     self.address,
                                     name,
                                     fee,
                                     self.owner,
                                     signers,
                                     *args,
                                     shard_mask=shard_mask)
 def test_resource_to_shard_mask(self):
     num_lanes = 4
     bv = ShardMask.resources_to_shard_mask(['abc', 'def', 'XYZ'],
                                            num_lanes)
     self.assertEqual(bv._size, num_lanes)
     self.assertEqual(bv.as_binary(), '00001110')
Beispiel #8
0
 def test_state_to_address(self):
     address = ShardMask.state_to_address('foo.bar', 'xyz')
     self.assertEqual(address, 'foo.bar.state.xyz')
Beispiel #9
0
 def test_resource_to_shard_invalid_lane(self):
     # Test rejection of invalid lane number
     with self.assertRaises(AssertionError):
         ShardMask.resource_to_shard('abc', 3)