Beispiel #1
0
    def _post_transfer(self, engine: contracts.ApplicationEngine,
                       account_from: types.UInt160, account_to: types.UInt160,
                       amount: vm.BigInteger, data: vm.StackItem,
                       call_on_payment: bool) -> None:
        state = vm.ArrayStackItem(vm.ReferenceCounter())
        if account_from == types.UInt160.zero():
            state.append(vm.NullStackItem())
        else:
            state.append(vm.ByteStringStackItem(account_from.to_array()))
        if account_to == types.UInt160.zero():
            state.append(vm.NullStackItem())
        else:
            state.append(vm.ByteStringStackItem(account_to.to_array()))
        state.append(vm.IntegerStackItem(amount))

        msgrouter.interop_notify(self.hash, "Transfer", state)

        # wallet or smart contract
        if not call_on_payment \
                or account_to == types.UInt160.zero() \
                or contracts.ManagementContract().get_contract(engine.snapshot, account_to) is None:
            return

        if account_from == types.UInt160.zero():
            from_: vm.StackItem = vm.NullStackItem()
        else:
            from_ = vm.ByteStringStackItem(account_from.to_array())
        engine.call_from_native(
            self.hash, account_to, "onNEP17Payment",
            [from_, vm.IntegerStackItem(amount), data])
Beispiel #2
0
    def transfer_helper(self, contract: contracts.NativeContract,
                        from_account: types.UInt160, to_account: types.UInt160,
                        amount: vm.BigInteger):
        engine = test_engine(has_snapshot=True)
        block = test_block(0)
        # set or we won't pass the native deploy call
        engine.snapshot.persisting_block = block
        engine.invoke_syscall_by_name("Neo.Native.Deploy")
        engine.invocation_stack.pop()  # we no longer need the default script
        engine.script_container = TestIVerifiable()
        engine.script_container.script_hashes = [from_account]

        sb = vm.ScriptBuilder()
        sb.emit_push(amount)
        sb.emit_push(to_account.to_array())
        sb.emit_push(from_account.to_array())
        sb.emit_push(3)
        sb.emit(vm.OpCode.PACK)
        sb.emit_push(b'transfer')
        sb.emit_push(contract.script_hash.to_array())
        sb.emit_syscall(syscall_name_to_int("System.Contract.Call"))
        engine.load_script(vm.Script(sb.to_array()))

        engine.snapshot.contracts.put(
            storage.ContractState(sb.to_array(), contracts.ContractManifest()))
        return engine
Beispiel #3
0
    def transfer_helper(self, contract: contracts.NativeContract,
                        from_account: types.UInt160, to_account: types.UInt160,
                        amount: vm.BigInteger):
        engine = test_engine(has_snapshot=True)
        block = test_block(0)
        # set or we won't pass the native deploy call
        engine.snapshot.persisting_block = block
        engine.invocation_stack.pop()  # we no longer need the default script
        engine.script_container = TestIVerifiable()
        engine.script_container.script_hashes = [from_account]

        sb = vm.ScriptBuilder()
        sb.emit(vm.OpCode.PUSHNULL)
        sb.emit_push(amount)
        sb.emit_push(to_account.to_array())
        sb.emit_push(from_account.to_array())
        sb.emit_push(4)
        sb.emit(vm.OpCode.PACK)
        sb.emit_push(15)  # callflags
        sb.emit_push(b'transfer')
        sb.emit_push(contract.hash.to_array())
        sb.emit_syscall(syscall_name_to_int("System.Contract.Call"))
        engine.load_script(vm.Script(sb.to_array()))

        nef = contracts.NEF(script=sb.to_array())
        manifest = contracts.ContractManifest("test_contract")
        contract_state = contracts.ContractState(
            1, nef, manifest, 0,
            contract_hash(from_account, nef.checksum, manifest.name))
        engine.snapshot.contracts.put(contract_state)
        return engine
Beispiel #4
0
    def _internal_contract_get(self, hash: types.UInt160):
        contract_bytes = self._real_db.get(DBPrefixes.CONTRACTS +
                                           hash.to_array())
        if contract_bytes is None:
            raise KeyError

        return contracts.ContractState.deserialize_from_bytes(contract_bytes)
Beispiel #5
0
    def _internal_contract_delete(self, hash: types.UInt160, batch=None):
        if batch:
            db = batch
        else:
            db = self._real_db

        db.delete(DBPrefixes.CONTRACTS + hash.to_array())
Beispiel #6
0
    def transfer(self, engine: contracts.ApplicationEngine, account_to: types.UInt160, token_id: bytes) -> bool:
        if account_to == types.UInt160.zero():
            raise ValueError("To account can't be zero")

        key_token = self.key_token + token_id
        storage_item = engine.snapshot.storages.try_get(key_token, read_only=True)
        if storage_item is None:
            raise ValueError("Token state not found")
        token_state = NFTState.deserialize_from_bytes(storage_item.value)
        if token_state.owner != engine.calling_scripthash and engine.checkwitness(token_state.owner):
            return False
        if token_state.owner != account_to:
            token = NFTState.from_stack_item(engine.snapshot.storages.get(key_token, read_only=False))
            key_from = self.key_account + token_state.owner.to_array
            account_state = engine.snapshot.storages.get(key_from).get(NFTAccountState)
            account_state.remove(token_id)
            if account_state.balance == 0:
                engine.snapshot.storages.delete(key_from)
            token.owner = account_to
            key_to = self.key_account + account_to.to_array()
            storage_item = engine.snapshot.storages.try_get(key_to, read_only=False)
            if storage_item is None:
                storage_item = storage.StorageItem(NFTAccountState().to_array())
                engine.snapshot.storages.put(key_to, storage_item)
            storage_item.get(NFTAccountState).add(token_id)
            self.on_transferred(engine, token.owner, token)

        self._post_transfer(engine, token_state.owner, account_to, token_id)
        return True
Beispiel #7
0
def contract_hash(sender: types.UInt160, checksum: int,
                  name: str) -> types.UInt160:
    sb = vm.ScriptBuilder()
    sb.emit(vm.OpCode.ABORT)
    sb.emit_push(sender.to_array())
    sb.emit_push(checksum)
    sb.emit_push(name)
    return to_script_hash(sb.to_array())
Beispiel #8
0
 def tokens_of(self, snapshot: storage.Snapshot, owner: types.UInt160) -> interop.IIterator:
     storage_item_account = snapshot.storages.try_get(self.key_account + owner.to_array(), read_only=True)
     reference_counter = vm.ReferenceCounter()
     if storage_item_account is None:
         return interop.ArrayWrapper(vm.ArrayStackItem(reference_counter))
     account = storage_item_account.get(NFTAccountState)
     tokens: List[vm.StackItem] = list(map(lambda t: vm.ByteStringStackItem(t), account.tokens))
     return interop.ArrayWrapper(vm.ArrayStackItem(reference_counter, tokens))
 def call_from_native(self, calling_scripthash: types.UInt160,
                      hash_: types.UInt160, method: str,
                      args: List[vm.StackItem]) -> None:
     ctx = self.current_context
     self._contract_call_internal(hash_, method, contracts.CallFlags.ALL,
                                  False, args)
     self.current_context.calling_scripthash_bytes = calling_scripthash.to_array(
     )
     while self.current_context != ctx:
         self.step_out()
Beispiel #10
0
    def script_hash_to_address(script_hash: types.UInt160) -> str:
        """
        Converts the specified script hash to an address.

        Args:
            script_hash: script hash to convert.
        """
        version = settings.network.account_version  # this is the current Neo's protocol version
        data = version.to_bytes(1, 'little') + script_hash.to_array()

        return base58.b58encode_check(data).decode('utf-8')
Beispiel #11
0
    def is_valid(self, contract_hash: types.UInt160) -> bool:
        """
        Validate if the group has agreed on allowing the specific contract_hash.

        Args:
            contract_hash:
        """
        return cryptography.verify_signature(
            contract_hash.to_array(), self.signature,
            self.public_key.encode_point(False),
            cryptography.ECCCurve.SECP256R1)
Beispiel #12
0
    def _post_transfer(self,
                       engine: contracts.ApplicationEngine,
                       account_from: types.UInt160,
                       account_to: types.UInt160,
                       token_id: bytes) -> None:
        state = vm.ArrayStackItem(engine.reference_counter)
        if account_from == types.UInt160.zero():
            state.append(vm.NullStackItem())
        else:
            state.append(vm.ByteStringStackItem(account_from.to_array()))
        if account_to == types.UInt160.zero():
            state.append(vm.NullStackItem())
        else:
            state.append(vm.ByteStringStackItem(account_to.to_array()))
        state.append(vm.IntegerStackItem(1))
        state.append(vm.ByteStringStackItem(token_id))

        msgrouter.interop_notify(self.hash, "Transfer", state)

        if account_to != types.UInt160.zero() and \
                contracts.ManagementContract().get_contract(engine.snapshot, account_to) is not None:
            engine.call_from_native(self.hash, account_to, "onNEP17Payment", list(state))
Beispiel #13
0
    def _internal_storage_find(self, contract_script_hash: types.UInt160, key_prefix: bytes):
        prefix = DBPrefixes.STORAGES + contract_script_hash.to_array() + key_prefix

        res = {}
        with self._real_db.iterator(prefix=prefix, include_key=True, include_value=True) as it:
            for key, value in it:
                # strip off prefix
                k = storage.StorageKey.deserialize_from_bytes(key[1:])
                v = storage.StorageItem.deserialize_from_bytes(value)
                res[k] = v

        # yielding outside of iterator to make sure the LevelDB iterator is closed and not leaking resources
        for k, v in res.items():
            yield k, v
Beispiel #14
0
 def _unblock_account(self, engine: contracts.ApplicationEngine,
                      account: types.UInt160) -> bool:
     """
     Should only be called through syscalls
     """
     if not self._check_committee(engine):
         return False
     storage_key = self.key_blocked_account + account.to_array()
     storage_item = engine.snapshot.storages.try_get(storage_key,
                                                     read_only=False)
     if storage_item is None:
         return False
     else:
         engine.snapshot.storages.delete(storage_key)
     return True
Beispiel #15
0
    def is_blocked(self, snapshot: storage.Snapshot,
                   account: types.UInt160) -> bool:
        """
        Check if the account is blocked

        Transaction from blocked accounts will be rejected by the consensus nodes.
        """

        si = snapshot.storages.try_get(self.key_blocked_account +
                                       account.to_array(),
                                       read_only=True)
        if si is None:
            return False
        else:
            return True
Beispiel #16
0
 def balance_of(self, snapshot: storage.Snapshot, owner: types.UInt160) -> vm.BigInteger:
     storage_item = snapshot.storages.try_get(self.key_account + owner.to_array(), read_only=True)
     if storage_item is None:
         return vm.BigInteger.zero()
     return NFTAccountState.deserialize_from_bytes(storage_item.value).balance