コード例 #1
0
    def test_storage_find(self):
        # settings.storage.default_provider = 'leveldb'
        engine = test_engine(has_snapshot=True)
        engine.snapshot.contracts.put(self.contract)

        storage_key1 = storage.StorageKey(self.contract.id, b'\x01')
        storage_item1 = storage.StorageItem(b'\x11')
        engine.snapshot.storages.put(storage_key1, storage_item1)
        storage_key2 = storage.StorageKey(self.contract.id, b'\x02')
        storage_item2 = storage.StorageItem(b'\x22')
        engine.snapshot.storages.put(storage_key2, storage_item2)

        ctx = engine.invoke_syscall_by_name("System.Storage.GetContext")
        engine.push(vm.IntegerStackItem(contracts.FindOptions.NONE))
        engine.push(vm.ByteStringStackItem(storage_key1.key))
        engine.push(vm.StackItem.from_interface(ctx))

        it = engine.invoke_syscall_by_name("System.Storage.Find")
        self.assertIsInstance(it, interop.StorageIterator)

        with self.assertRaises(ValueError) as context:
            it.value()
        self.assertEqual(
            "Cannot call 'value' without having advanced the iterator at least once",
            str(context.exception))

        self.assertTrue(it.next())

        struct = it.value()  # 0 key, 1 value
        self.assertEqual(storage_item1.value, struct[1].to_array())
コード例 #2
0
 def test_eq(self):
     contract = types.UInt160.zero()
     key_val = b'\0x01\x02\x03'
     sk = storage.StorageKey(contract, key_val)
     sk2 = storage.StorageKey(contract, key_val)
     self.assertFalse(sk == object())
     self.assertTrue(sk == sk2)
コード例 #3
0
    def test_storage_find(self):
        engine = test_engine(has_snapshot=True)
        engine.snapshot.contracts.put(self.contract)

        storage_key1 = storage.StorageKey(self.contract.script_hash(), b'\x01')
        storage_item1 = storage.StorageItem(b'\x11', is_constant=False)
        engine.snapshot.storages.put(storage_key1, storage_item1)
        storage_key2 = storage.StorageKey(self.contract.script_hash(), b'\x02')
        storage_item2 = storage.StorageItem(b'\x22', is_constant=False)
        engine.snapshot.storages.put(storage_key2, storage_item2)

        ctx = engine.invoke_syscall_by_name("System.Storage.GetContext")
        engine.push(vm.ByteStringStackItem(storage_key1.key))
        engine.push(vm.StackItem.from_interface(ctx))

        it = engine.invoke_syscall_by_name("System.Storage.Find")
        self.assertIsInstance(it, interop.StorageIterator)
        it.next()
        self.assertEqual(storage_key1.key, it.key().to_array())
        self.assertEqual(storage_item1.value, it.value().to_array())

        it.next()
        with self.assertRaises(ValueError) as context:
            it.key()
        self.assertEqual(
            "Cannot call 'key' without having advanced the iterator at least once",
            str(context.exception))
        with self.assertRaises(ValueError) as context:
            it.value()
        self.assertEqual(
            "Cannot call 'value' without having advanced the iterator at least once",
            str(context.exception))
コード例 #4
0
    def test_contract_update_exceptions6(self):
        # asking to update with a new script but with an invalid manifest (new manifest does not support storage,
        # while the old contract has existing storage)
        engine = test_engine(has_snapshot=True, default_script=False)

        contract_old = storage.ContractState(hello_world_nef.script,
                                             deepcopy(hello_world_manifest))
        contract_old.manifest.features |= contracts.ContractFeatures.HAS_STORAGE
        engine.snapshot.contracts.put(contract_old)

        storage_key = storage.StorageKey(contract_old.script_hash(),
                                         b'firstkey')
        storage_item = storage.StorageItem(b'firstitem')
        engine.snapshot.storages.put(storage_key, storage_item)

        # we load the stored as script to properly setup "engine.current_scripthash"
        engine.load_script(vm.Script(contract_old.script))
        # next we push the necessary items on the stack before calling the update funcztion
        # we take the matching manifest and change it to have no storage
        bad_manifest = deepcopy(bye_world_manifest)
        bad_manifest.features &= ~contracts.ContractFeatures.HAS_STORAGE
        engine.push(vm.ByteStringStackItem(str(bad_manifest).encode()))
        engine.push(vm.ByteStringStackItem(bye_world_nef.script))

        with self.assertRaises(ValueError) as context:
            engine.invoke_syscall_by_name("System.Contract.Update")
        self.assertEqual(
            "Error: New contract does not support storage while old contract has existing storage",
            str(context.exception))
コード例 #5
0
    def test_storage_get_ok2(self):
        # this is basically the same as `test_storage_get_ok`
        # but performed by executing a script
        # it exists to validate that the `Optional[bytes]` return value is converted properly
        engine = test_engine(has_snapshot=True)
        script = vm.ScriptBuilder()
        script.emit(vm.OpCode.PUSH1)
        script.emit_syscall(syscall_name_to_int("System.Storage.GetContext"))
        script.emit_syscall(syscall_name_to_int("System.Storage.Get"))
        engine.load_script(vm.Script(script.to_array()))

        nef = contracts.NEF(script=script.to_array())
        contract_hash = to_script_hash(nef.script)
        contract = contracts.ContractState(1, nef, self.manifest, 0,
                                           contract_hash)
        engine.snapshot.contracts.put(contract)

        storage_key = storage.StorageKey(contract.id, b'\x01')
        storage_item = storage.StorageItem(b'\x11')
        engine.snapshot.storages.put(storage_key, storage_item)

        engine.execute()
        self.assertEqual(vm.VMState.HALT, engine.state)
        self.assertEqual(1, len(engine.result_stack))
        item = engine.result_stack.pop()
        self.assertEqual(storage_item.value, item.to_array())
コード例 #6
0
ファイル: storage.py プロジェクト: CityOfZion/neo-mamba
def storage_put(engine: contracts.ApplicationEngine,
                context: storage.StorageContext, key: bytes,
                value: bytes) -> None:
    if len(key) > MAX_STORAGE_KEY_SIZE:
        raise ValueError(
            f"Storage key length exceeds maximum of {MAX_STORAGE_KEY_SIZE}")
    if len(value) > MAX_STORAGE_VALUE_SIZE:
        raise ValueError(
            f"Storage value length exceeds maximum of {MAX_STORAGE_VALUE_SIZE}"
        )
    if context.is_read_only:
        raise ValueError("Cannot persist to read-only storage context")

    storage_key = storage.StorageKey(context.id, key)
    item = engine.snapshot.storages.try_get(storage_key, read_only=False)

    if item is None:
        new_data_len = len(key) + len(value)
        item = storage.StorageItem(b'')
        engine.snapshot.storages.put(storage_key, item)
    else:
        if len(value) == 0:
            new_data_len = 0
        elif len(value) <= len(item.value):
            new_data_len = (len(value) - 1) // 4 + 1
        elif len(item.value) == 0:
            new_data_len = len(value)
        else:
            new_data_len = (len(item.value) - 1) // 4 + 1 + len(value) - len(
                item.value)

    engine.add_gas(new_data_len * engine.STORAGE_PRICE)
    item.value = value
コード例 #7
0
    def test_storage_put_new(self):
        # see `test_storage_get_key_not_found()` for a description on why the storage is setup with a script as is

        # setup
        engine = test_engine(has_snapshot=True)
        script = vm.ScriptBuilder()
        script.emit(vm.OpCode.PUSH2)  # storage put value
        script.emit(vm.OpCode.PUSH1)  # storage put key
        script.emit_syscall(syscall_name_to_int("System.Storage.GetContext"))
        script.emit_syscall(syscall_name_to_int("System.Storage.Put"))
        engine.load_script(vm.Script(script.to_array()))

        nef = contracts.NEF(script=script.to_array())
        manifest = contracts.ContractManifest(f"contractname1")
        manifest.abi.methods = [
            contracts.ContractMethodDescriptor(
                "test_func", 0, [], contracts.ContractParameterType.ANY, True)
        ]
        hash_ = to_script_hash(nef.script)

        contract = contracts.ContractState(1, nef, manifest, 0, hash_)
        engine.snapshot.contracts.put(contract)

        engine.execute()

        self.assertEqual(vm.VMState.HALT, engine.state)
        storage_key = storage.StorageKey(1, b'\x01')
        item = engine.snapshot.storages.try_get(storage_key)
        self.assertIsNotNone(item)
        self.assertEqual(b'\x02', item.value)
コード例 #8
0
    def test_policy_unblock_account(self):
        # we've tested the full round trip via "System.Contract.Call" in the test
        # test_policy_set_and_get_blocked_accounts()
        # Here we take the shortcut and test the unblock account function directly
        engine = test_engine(has_snapshot=True)
        block = test_block(0)
        engine.snapshot.persisting_block = block
        engine.invoke_syscall_by_name("Neo.Native.Deploy")

        # we must add a script_container with valid signature to pass the check_comittee() validation check
        # in the function itself
        engine.script_container = TestIVerifiable()
        validator = settings.standby_committee[0]
        script_hash = to_script_hash(
            contracts.Contract.create_multisig_redeemscript(1, [validator]))
        engine.script_container.script_hashes = [script_hash]

        policy = contracts.PolicyContract()
        account_not_found = types.UInt160(data=b'\x11' * 20)
        account = types.UInt160.zero()
        self.assertTrue(policy._block_account(engine, account))
        self.assertFalse(policy._unblock_account(engine, account_not_found))
        self.assertTrue(policy._unblock_account(engine, account))
        storage_key = storage.StorageKey(policy.script_hash,
                                         policy._PREFIX_BLOCKED_ACCOUNTS)
        storage_item = engine.snapshot.storages.try_get(storage_key)
        self.assertIsNotNone(storage_item)
        self.assertEqual(b'\x00', storage_item.value)
コード例 #9
0
ファイル: storage.py プロジェクト: simplitech/neo-mamba
def _storage_put_internal(engine: contracts.ApplicationEngine,
                          context: storage.StorageContext, key: bytes,
                          value: bytes, flags: storage.StorageFlags) -> None:
    if len(key) > MAX_STORAGE_KEY_SIZE:
        raise ValueError(
            f"Storage key length exceeds maximum of {MAX_STORAGE_KEY_SIZE}")
    if len(value) > MAX_STORAGE_VALUE_SIZE:
        raise ValueError(
            f"Storage value length exceeds maximum of {MAX_STORAGE_VALUE_SIZE}"
        )
    if context.is_read_only:
        raise ValueError("Cannot persist to read-only storage context")

    storage_key = storage.StorageKey(context.script_hash, key)
    item = engine.snapshot.storages.try_get(storage_key, read_only=False)

    is_constant = storage.StorageFlags.CONSTANT in flags
    if item is None:
        new_data_len = len(key) + len(value)
        item = storage.StorageItem(b'', is_constant)
        engine.snapshot.storages.put(storage_key, item)
    else:
        if item.is_constant:
            raise ValueError("StorageItem is marked as constant")
        if len(value) <= len(item.value):
            new_data_len = 1
        else:
            new_data_len = len(value) - len(item.value)

    engine.add_gas(new_data_len * STORAGE_PRICE)
    item.value = value
    item.is_constant = is_constant
コード例 #10
0
    def test_storage_get_key_not_found(self):
        engine = test_engine(has_snapshot=True)
        script = vm.ScriptBuilder()
        # key parameter for the `Get` syscall
        script.emit(vm.OpCode.PUSH2)
        script.emit_syscall(syscall_name_to_int("System.Storage.GetContext"))
        # at this point our stack looks like follows
        # * storage context
        # * key
        script.emit_syscall(syscall_name_to_int("System.Storage.Get"))
        engine.load_script(vm.Script(script.to_array()))

        # we set the script parameter of the ContractState to our script
        # which ensures that `engine.current_scripthash` matches the script we manually build above
        # this basically means the engine thinks it is running a smart contract that we can find in our storage
        # which in turns enables us to call the `System.Storage.GetContext` syscall
        contract = storage.ContractState(script=script.to_array(),
                                         _manifest=self.manifest)
        engine.snapshot.contracts.put(contract)

        storage_key = storage.StorageKey(contract.script_hash(), b'\x01')
        storage_item = storage.StorageItem(b'\x11')
        engine.snapshot.storages.put(storage_key, storage_item)

        engine.execute()
        self.assertEqual(vm.VMState.HALT, engine.state)
        self.assertEqual(1, len(engine.result_stack))
        item = engine.result_stack.pop()
        self.assertIsInstance(item, vm.NullStackItem)
コード例 #11
0
    def test_storage_put_overwrite(self):
        # test with new data being shorter than the old data
        engine = test_engine(has_snapshot=True)
        key = b'\x01'
        storage_key = storage.StorageKey(types.UInt160.zero(), key)
        storage_item = storage.StorageItem(b'\x11\x22\x33', is_constant=False)
        engine.snapshot.storages.put(storage_key, storage_item)

        ctx = storage.StorageContext(types.UInt160.zero(), is_read_only=False)
        new_item_value = b'\x11\x22'
        contracts.interop._storage_put_internal(engine, ctx, key,
                                                new_item_value,
                                                storage.StorageFlags.NONE)

        item = engine.snapshot.storages.get(storage_key)
        self.assertIsNotNone(item)
        self.assertEqual(new_item_value, item.value)

        # now test with data being longer than before
        longer_item_value = b'\x11\x22\x33\x44'
        contracts.interop._storage_put_internal(engine, ctx, key,
                                                longer_item_value,
                                                storage.StorageFlags.NONE)

        item = engine.snapshot.storages.get(storage_key)
        self.assertIsNotNone(item)
        self.assertEqual(longer_item_value, item.value)
コード例 #12
0
    def test_storage_put_new(self):
        # see `test_storage_get_key_not_found()` for a description on why the storage is setup with a script as is

        for i in range(2):
            # setup
            engine = test_engine(has_snapshot=True)
            script = vm.ScriptBuilder()
            if i == 0:
                script.emit(vm.OpCode.PUSH2)  # storage put value
                script.emit(vm.OpCode.PUSH1)  # storage put key
                script.emit_syscall(
                    syscall_name_to_int("System.Storage.GetContext"))
                script.emit_syscall(syscall_name_to_int("System.Storage.Put"))
            else:
                script.emit(vm.OpCode.PUSH0)  # storage put call flags
                script.emit(vm.OpCode.PUSH2)  # storage put value
                script.emit(vm.OpCode.PUSH1)  # storage put key
                script.emit_syscall(
                    syscall_name_to_int("System.Storage.GetContext"))
                script.emit_syscall(
                    syscall_name_to_int("System.Storage.PutEx"))
            engine.load_script(vm.Script(script.to_array()))

            contract = storage.ContractState(script=script.to_array(),
                                             _manifest=self.manifest)
            engine.snapshot.contracts.put(contract)

            engine.execute()

            self.assertEqual(vm.VMState.HALT, engine.state)
            storage_key = storage.StorageKey(contract.script_hash(), b'\x01')
            item = engine.snapshot.storages.try_get(storage_key)
            self.assertIsNotNone(item)
            self.assertEqual(b'\x02', item.value)
コード例 #13
0
    def test_storage_get_key_not_found(self):
        engine = test_engine(has_snapshot=True, has_container=True)
        script = vm.ScriptBuilder()
        # key parameter for the `Storage.Get` syscall
        script.emit(vm.OpCode.PUSH2)
        script.emit_syscall(syscall_name_to_int("System.Storage.GetContext"))
        # at this point our stack looks like follows
        # * storage context
        # * key
        script.emit_syscall(syscall_name_to_int("System.Storage.Get"))
        engine.load_script(vm.Script(script.to_array()))

        # we have to store our contract or some sanity checks will fail (like getting a StorageContext
        nef = contracts.NEF(script=script.to_array())
        contract = contracts.ContractState(1, nef, self.manifest, 0,
                                           to_script_hash(nef.script))
        engine.snapshot.contracts.put(contract)

        storage_key = storage.StorageKey(contract.id, b'\x01')
        storage_item = storage.StorageItem(b'\x11')
        engine.snapshot.storages.put(storage_key, storage_item)

        engine.execute()
        self.assertEqual(vm.VMState.HALT, engine.state)
        self.assertEqual(1, len(engine.result_stack))
        item = engine.result_stack.pop()
        self.assertIsInstance(item, vm.NullStackItem)
コード例 #14
0
ファイル: nonfungible.py プロジェクト: DanPopa46/neo-mamba
    def init(self):
        super(NonFungibleToken, self).init()
        self.key_total_suppply = storage.StorageKey(self._id, b'\x0b')
        self.key_token = storage.StorageKey(self._id, b'\x05')
        self.key_account = storage.StorageKey(self._id, b'\x07')

        self.manifest.abi.events = [
            contracts.ContractEventDescriptor(
                "Transfer",
                parameters=[
                    contracts.ContractParameterDefinition("from", contracts.ContractParameterType.HASH160),
                    contracts.ContractParameterDefinition("to", contracts.ContractParameterType.HASH160),
                    contracts.ContractParameterDefinition("amount", contracts.ContractParameterType.INTEGER),
                    contracts.ContractParameterDefinition("tokenId", contracts.ContractParameterType.BYTEARRAY)
                ]
            )
        ]
コード例 #15
0
ファイル: storage.py プロジェクト: simplitech/neo-mamba
def storage_get(engine: contracts.ApplicationEngine,
                context: storage.StorageContext,
                key: bytes) -> Optional[bytes]:
    storage_key = storage.StorageKey(context.script_hash, key)
    item = engine.snapshot.storages.try_get(storage_key, read_only=True)
    if item is not None:
        return item.value
    return None
コード例 #16
0
    def test_len(self):
        contract = 1
        key_val = b'\x01\x02\x03'
        sk = storage.StorageKey(contract, key_val)

        # contract id is serialized to int32
        expected_len = 4 + len(key_val)
        self.assertEqual(expected_len, len(sk))
コード例 #17
0
    def create_key(self, prefix: bytes) -> storage.StorageKey:
        """
        Helper to create a storage key for the contract

        Args:
            prefix: the storage prefix to be used
        """
        return storage.StorageKey(self._id, prefix)
コード例 #18
0
    def init(self):
        super(FungibleToken, self).init()

        self.key_account = storage.StorageKey(self._id, b'\x14')
        self.key_total_supply = storage.StorageKey(self._id, b'\x0B')

        self.manifest.supported_standards = ["NEP-17"]
        self.manifest.abi.events = [
            contracts.ContractEventDescriptor(
                "Transfer",
                parameters=[
                    contracts.ContractParameterDefinition("from", contracts.ContractParameterType.HASH160),
                    contracts.ContractParameterDefinition("to", contracts.ContractParameterType.HASH160),
                    contracts.ContractParameterDefinition("amount", contracts.ContractParameterType.INTEGER)
                ]
            )
        ]
        self.factor = pow(vm.BigInteger(10), vm.BigInteger(self._decimals))
コード例 #19
0
    def test_serialization(self):
        contract = 1
        key_val = b'\x01\x02\x03'
        sk = storage.StorageKey(contract, key_val)

        # test serialize
        expected_value = b'\x01\x00\x00\x00' + key_val
        self.assertEqual(expected_value, sk.to_array())
        # test deserialize
        self.assertEqual(sk, storage.StorageKey.deserialize_from_bytes(expected_value))
コード例 #20
0
    def test_various(self):
        contract = 1
        key_val = b'\x01\x02\x03'
        sk = storage.StorageKey(contract, key_val)
        # test __repr__ in absence of __str__
        self.assertIn("<StorageKey at ", str(sk))
        self.assertIn(r"[1] b'\x01\x02\x03'", str(sk))

        # test __hash__
        self.assertEqual(2161234437, hash(sk))
コード例 #21
0
ファイル: storage.py プロジェクト: simplitech/neo-mamba
def storage_delete(engine: contracts.ApplicationEngine,
                   context: storage.StorageContext, key: bytes) -> None:
    if context.is_read_only:
        raise ValueError("Cannot delete from read-only storage context")
    storage_key = storage.StorageKey(context.script_hash, key)
    item = engine.snapshot.storages.try_get(storage_key)
    if item and item.is_constant:
        raise ValueError(
            "Cannot delete a storage item that is marked constant")
    engine.snapshot.storages.delete(storage_key)
コード例 #22
0
    def test_len(self):
        contract = types.UInt160.zero()
        key_val = b'\x01\x02\x03'
        sk = storage.StorageKey(contract, key_val)

        group_size = 16
        group_remainder_size = 1
        # len(key_val) is smaller than group_size
        # thus we get (see implementation of write_bytes_with_grouping) to understand the logic
        expected_len = len(contract) + group_size + group_remainder_size
        self.assertEqual(expected_len, len(sk))
コード例 #23
0
    def test_addition(self):
        sk = storage.StorageKey(1, b'\x01')
        new_sk = sk + b'\x02'
        self.assertNotEqual(id(sk), id(new_sk))
        self.assertNotEqual(sk.key, new_sk.key)
        self.assertEqual(new_sk.key, b'\x01\x02')

        # test with serializable type
        new_sk2 = sk + types.UInt160.zero()
        self.assertEqual(new_sk2.key, b'\x01' + b'\x00' * 20)

        with self.assertRaises(TypeError) as context:
            sk + 1
        self.assertEqual("unsupported operand type(s) for +: 'StorageKey' and 'int'", str(context.exception))
コード例 #24
0
    def test_serialization(self):
        contract = types.UInt160.zero()
        key_val = b'\x01\x02\x03'
        key_val_padding = bytearray(16 - len(key_val))
        key_val_group_remainder = b'\x03'
        sk = storage.StorageKey(contract, key_val)

        # test serialize
        expected_value = contract.to_array(
        ) + key_val + key_val_padding + key_val_group_remainder
        self.assertEqual(expected_value, sk.to_array())
        # test deserialize
        self.assertEqual(
            sk, storage.StorageKey.deserialize_from_bytes(expected_value))
コード例 #25
0
    def test_storage_get_ok(self):
        engine = test_engine(has_snapshot=True)
        engine.snapshot.contracts.put(self.contract)

        storage_key = storage.StorageKey(self.contract.id, b'\x01')
        storage_item = storage.StorageItem(b'\x11')
        engine.snapshot.storages.put(storage_key, storage_item)

        ctx = engine.invoke_syscall_by_name("System.Storage.GetContext")
        engine.push(vm.ByteStringStackItem(storage_key.key))
        engine.push(vm.StackItem.from_interface(ctx))
        returned_value = engine.invoke_syscall_by_name("System.Storage.Get")

        self.assertEqual(storage_item.value, returned_value)
コード例 #26
0
    def test_delete_ok(self):
        engine = test_engine(has_snapshot=True)
        engine.snapshot.contracts.put(self.contract)

        storage_key = storage.StorageKey(self.contract.id, b'\x01')
        storage_item = storage.StorageItem(b'\x11')
        engine.snapshot.storages.put(storage_key, storage_item)

        ctx = engine.invoke_syscall_by_name("System.Storage.GetContext")
        engine.push(vm.ByteStringStackItem(storage_key.key))
        engine.push(vm.StackItem.from_interface(ctx))

        engine.invoke_syscall_by_name("System.Storage.Delete")

        self.assertIsNone(engine.snapshot.storages.try_get(storage_key))
コード例 #27
0
    def test_storage_delete_constant_item(self):
        engine = test_engine(has_snapshot=True)
        engine.snapshot.contracts.put(self.contract)

        storage_key = storage.StorageKey(self.contract.script_hash(), b'\x01')
        storage_item = storage.StorageItem(b'\x11', is_constant=True)
        engine.snapshot.storages.put(storage_key, storage_item)

        ctx = engine.invoke_syscall_by_name("System.Storage.GetContext")
        engine.push(vm.ByteStringStackItem(storage_key.key))
        engine.push(vm.StackItem.from_interface(ctx))

        with self.assertRaises(ValueError) as context:
            engine.invoke_syscall_by_name("System.Storage.Delete")
        self.assertEqual(
            "Cannot delete a storage item that is marked constant",
            str(context.exception))
コード例 #28
0
    def test_storage_delete_readonly_context(self):
        engine = test_engine(has_snapshot=True)

        engine.snapshot.contracts.put(self.contract)

        storage_key = storage.StorageKey(self.contract.id, b'\x01')
        storage_item = storage.StorageItem(b'\x11')
        engine.snapshot.storages.put(storage_key, storage_item)

        ctx = engine.invoke_syscall_by_name(
            "System.Storage.GetReadOnlyContext")
        engine.push(vm.ByteStringStackItem(storage_key.key))
        engine.push(vm.StackItem.from_interface(ctx))

        with self.assertRaises(ValueError) as context:
            engine.invoke_syscall_by_name("System.Storage.Delete")
        self.assertEqual("Cannot delete from read-only storage context",
                         str(context.exception))
コード例 #29
0
    def test_contract_destroy_ok(self):
        engine = test_engine(has_snapshot=True, default_script=False)
        # for this test we modify our contract to also have storage, to validate it gets cleared properly
        contract = storage.ContractState(hello_world_nef.script,
                                         deepcopy(hello_world_manifest))
        contract.manifest.features |= contracts.ContractFeatures.HAS_STORAGE
        engine.snapshot.contracts.put(contract)

        storage_key = storage.StorageKey(contract.script_hash(), b'firstkey')
        storage_item = storage.StorageItem(b'firstitem')
        engine.snapshot.storages.put(storage_key, storage_item)

        # setup the engine by loading the contract script such that we can call destroy on _that_ contract
        engine.load_script(vm.Script(contract.script))
        engine.invoke_syscall_by_name("System.Contract.Destroy")
        self.assertIsNone(
            engine.snapshot.contracts.try_get(contract.script_hash()))
        self.assertIsNone(engine.snapshot.storages.try_get(storage_key))
コード例 #30
0
    def test_transfer_full_balance(self):
        gas = contracts.GasToken()

        manifest = contracts.ContractManifest()
        manifest.features = contracts.ContractFeatures.PAYABLE
        state_to = storage.ContractState(b'\x00' * 20, manifest)
        account_to = state_to.script_hash()

        account_from = types.UInt160(b'\x01' * 20)
        storage_key_from = storage.StorageKey(
            gas.script_hash, gas._PREFIX_ACCOUNT + account_from.to_array())
        account_from_state = gas._state()
        account_from_state.balance = vm.BigInteger(123)
        storage_item_from = storage.StorageItem(account_from_state.to_array())

        amount = account_from_state.balance

        engine = self.transfer_helper(gas, account_from, account_to, amount)
        # ensure the destination contract exists
        engine.snapshot.contracts.put(state_to)
        # ensure the source account has balance
        engine.snapshot.storages.put(storage_key_from, storage_item_from)

        transfer_event = ()

        def notify_listener(contract_script_hash, event, state):
            nonlocal transfer_event
            transfer_event = (contract_script_hash, event, state)

        msgrouter.interop_notify += notify_listener
        engine.execute()
        self.assertEqual(1, len(engine.result_stack))
        result = engine.result_stack.pop()
        self.assertTrue(result)
        self.assertEqual(gas.script_hash, transfer_event[0])
        self.assertEqual("Transfer", transfer_event[1])
        state_items = list(transfer_event[2])
        self.assertEqual(account_from,
                         types.UInt160(state_items[0].to_array()))
        self.assertEqual(account_to, types.UInt160(state_items[1].to_array()))
        self.assertEqual(amount, state_items[2].to_biginteger())

        # test that the source account is no longer present in storage as the balance is zero
        self.assertIsNone(engine.snapshot.storages.try_get(storage_key_from))