Exemple #1
0
    def test_getcallingscripthash(self):
        """
        Testing this requires 2 contracts

        1) caller_contract: uses a System.Contract.Call to call callee_contract. This will set the calling script hash on the ExecutionContext of the callee_contract
        2) callee_contract: uses a System.Runtime.GetCallingScriptHash to return the calling script
        """
        sb = vm.ScriptBuilder()
        sb.emit_syscall(
            syscall_name_to_int("System.Runtime.GetCallingScriptHash"))
        callee_contract_script = sb.to_array()
        callee_nef = contracts.NEF(script=callee_contract_script)
        callee_contract_name = "callee_contract"
        callee_manifest = contracts.ContractManifest(callee_contract_name)
        callee_manifest.abi.methods = [
            contracts.ContractMethodDescriptor(
                "test_func", 0, [], contracts.ContractParameterType.ANY, True)
        ]
        callee_contract_hash = contract_hash(types.UInt160.zero(),
                                             callee_nef.checksum,
                                             callee_contract_name)
        callee_contract = contracts.ContractState(1, callee_nef,
                                                  callee_manifest, 0,
                                                  callee_contract_hash)

        # create caller_contract script
        sb = vm.ScriptBuilder()
        sb.emit_dynamic_call(callee_contract.hash, "test_func")
        caller_script = sb.to_array()
        caller_nef = contracts.NEF(script=caller_script)
        caller_contract_name = "caller_contract"
        caller_manifest = contracts.ContractManifest(caller_contract_name)
        caller_contract_hash = contract_hash(types.UInt160.zero(),
                                             caller_nef.checksum,
                                             caller_contract_name)
        caller_contract = contracts.ContractState(2, caller_nef,
                                                  caller_manifest, 0,
                                                  caller_contract_hash)

        engine = test_engine(has_snapshot=True, default_script=False)
        engine.snapshot.contracts.put(callee_contract)
        engine.snapshot.contracts.put(caller_contract)
        engine.load_script(vm.Script(caller_script))
        engine.execute()

        self.assertEqual(vm.VMState.HALT, engine.state)
        self.assertEqual(1, len(engine.result_stack))
        item = engine.result_stack.pop()
        self.assertEqual(
            to_script_hash(caller_nef.script).to_array(), item.to_array())
Exemple #2
0
    def test_transfer_partial_balance_to_account_with_balance(self):
        gas = contracts.GasToken()

        manifest = contracts.ContractManifest("contract_name")
        nef = contracts.NEF(script=b'\x40')
        state_to = contracts.ContractState(
            1, nef, manifest, 0,
            contract_hash(types.UInt160.zero(), nef.checksum, manifest.name))
        account_to = state_to.hash
        storage_key_to = gas.key_account + account_to
        account_to_state = gas._state()
        account_to_state.balance = vm.BigInteger(100)
        storage_item_to = storage.StorageItem(account_to_state.to_array())

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

        amount = vm.BigInteger(50)

        engine = self.transfer_helper(gas, account_from, account_to, amount)
        # ensure the source and destination account have balances
        engine.snapshot.storages.put(storage_key_from, storage_item_from)
        engine.snapshot.storages.put(storage_key_to, storage_item_to)

        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.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())

        # validate from account is deducted by `amount`
        new_storage_account_from = engine.snapshot.storages.get(
            storage_key_from)
        new_account_state_from = gas._state.deserialize_from_bytes(
            new_storage_account_from.value)
        self.assertEqual(account_from_state.balance - amount,
                         new_account_state_from.balance)

        # validate to account is credited with `amount`
        new_storage_account_to = engine.snapshot.storages.get(storage_key_to)
        new_account_state_to = gas._state.deserialize_from_bytes(
            new_storage_account_to.value)
        self.assertEqual(account_to_state.balance + amount,
                         new_account_state_to.balance)
Exemple #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
Exemple #4
0
    def test_get_invocation_counter_ok(self):
        """
        We need to setup 2 contracts
        1) caller_contract: uses a System.Contract.Call to call callee_contract. This will increase the invocation counter of the callee contract
        2) callee_contract: uses a System.Runtime.GetInvocationCounter
        """
        engine = test_engine(has_snapshot=True,
                             has_container=False,
                             default_script=False)

        sb = vm.ScriptBuilder()
        sb.emit_syscall(
            syscall_name_to_int("System.Runtime.GetInvocationCounter"))
        callee_contract_script = sb.to_array()
        callee_nef = contracts.NEF(script=callee_contract_script)
        callee_manifest = contracts.ContractManifest("contract1")
        callee_manifest.abi.methods = [
            contracts.ContractMethodDescriptor(
                "test_func", 0, [], contracts.ContractParameterType.ANY, True)
        ]
        callee_contract = contracts.ContractState(
            1, callee_nef, callee_manifest, 0,
            contract_hash(types.UInt160.zero(), callee_nef.checksum,
                          callee_manifest.name))

        sb = vm.ScriptBuilder()
        sb.emit_dynamic_call(callee_contract.hash, "test_func")
        caller_script = sb.to_array()
        caller_nef = contracts.NEF(script=caller_script)
        caller_manifest = contracts.ContractManifest("contract2")
        caller_contract = contracts.ContractState(
            2, caller_nef, caller_manifest, 0,
            contract_hash(types.UInt160.zero(), caller_nef.checksum,
                          caller_manifest.name))

        engine.snapshot.contracts.put(callee_contract)
        engine.snapshot.contracts.put(caller_contract)
        engine.load_script(vm.Script(caller_script))
        engine.execute()

        self.assertEqual(vm.VMState.HALT, engine.state)
        self.assertEqual(1, len(engine.result_stack))
        item = engine.result_stack.pop()
        self.assertEqual(1, int(item))
Exemple #5
0
    def test_transfer_from_empty_account(self):
        gas = contracts.GasToken()
        manifest = contracts.ContractManifest("test_contract2")
        nef = contracts.NEF(script=b'\x40')
        state = contracts.ContractState(
            2, nef, manifest, 0,
            contract_hash(types.UInt160.zero(), nef.checksum, manifest.name))

        engine = self.transfer_helper(gas, types.UInt160.zero(), state.hash,
                                      vm.BigInteger(1))
        engine.snapshot.contracts.put(state)
        engine.execute()
        self.assertEqual(1, len(engine.result_stack))
        result = engine.result_stack.pop()
        self.assertFalse(result)
Exemple #6
0
    def test_transfer_full_balance(self):
        gas = contracts.GasToken()

        manifest = contracts.ContractManifest("contract_name_to")
        nef = contracts.NEF(script=b'\x40')
        state_to = contracts.ContractState(
            1, nef, manifest, 0,
            contract_hash(types.UInt160.zero(), nef.checksum, manifest.name))
        account_to = state_to.hash

        account_from = types.UInt160(b'\x01' * 20)
        storage_key_from = gas.key_account + account_from
        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 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.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))
Exemple #7
0
    def test_transfer_more_than_balance(self):
        gas = contracts.GasToken()
        account_from = types.UInt160.zero()
        storage_key_from = gas.key_account + account_from
        account_state = gas._state()
        account_state.balance = vm.BigInteger(123)
        storage_item_from = storage.StorageItem(account_state.to_array())

        manifest_to = contracts.ContractManifest("source_contract")
        nef_to = contracts.NEF(script=b'\x40')
        state_to = contracts.ContractState(
            1, nef_to, manifest_to, 0,
            contract_hash(types.UInt160.zero(), nef_to.checksum,
                          manifest_to.name))
        account_to = state_to.hash
        amount = account_state.balance + 1

        engine = self.transfer_helper(gas, account_from, account_to, amount)
        # ensure the source account has balance
        engine.snapshot.storages.put(storage_key_from, storage_item_from)
        engine.execute()
        self.assertEqual(1, len(engine.result_stack))
        result = engine.result_stack.pop()
        self.assertFalse(result)
Exemple #8
0
    def test_checkwitness_custom_groups(self):
        """
        We need to setup 2 contracts
        1) caller_contract: uses a System.Contract.Call to call callee_contract. This will set the calling script hash on the ExecutionContext of the callee_contract
        2) callee_contract: uses a System.Runtime.CheckWitness
        """
        engine = test_engine(has_snapshot=True, default_script=False)
        tx = test_tx()
        engine.script_container = tx
        '''
        Create the callee contract, which does a checkwitness on its caller.
        Checkwitness shall only pass if the caller == "caller_contract" as defined by CustomGroup
        '''
        sb = vm.ScriptBuilder()
        sb.emit_syscall(
            syscall_name_to_int("System.Runtime.GetCallingScriptHash")
        )  # get script hash of "caller_contract"
        sb.emit_syscall(syscall_name_to_int("System.Runtime.CheckWitness"))
        callee_contract_script = sb.to_array()
        callee_nef = contracts.NEF(script=callee_contract_script)
        callee_contract_name = "callee_contract"
        callee_manifest = contracts.ContractManifest(callee_contract_name)
        callee_manifest.abi.methods = [
            contracts.ContractMethodDescriptor(
                "test_func", 0, [], contracts.ContractParameterType.ANY, True)
        ]
        callee_contract_hash = contract_hash(tx.sender, callee_nef.checksum,
                                             callee_contract_name)
        callee_contract = contracts.ContractState(1, callee_nef,
                                                  callee_manifest, 0,
                                                  callee_contract_hash)

        sb = vm.ScriptBuilder()
        sb.emit_dynamic_call(callee_contract.hash, "test_func")
        caller_script = sb.to_array()
        caller_nef = contracts.NEF(script=caller_script)
        caller_contract_name = "caller_contract"
        caller_manifest = contracts.ContractManifest(caller_contract_name)

        keypair = cryptography.KeyPair(private_key=b'\x01' * 32)
        signature = cryptography.sign(caller_script, keypair.private_key)
        caller_manifest.groups = [
            contracts.ContractGroup(public_key=keypair.public_key,
                                    signature=signature)
        ]

        caller_contract_hash = contract_hash(tx.sender, caller_nef.checksum,
                                             caller_contract_name)
        caller_contract = contracts.ContractState(2, caller_nef,
                                                  caller_manifest, 0,
                                                  caller_contract_hash)
        engine.snapshot.contracts.put(caller_contract)
        engine.snapshot.contracts.put(callee_contract)
        engine.load_script(vm.Script(caller_script))

        tx.signers[0].scope = payloads.WitnessScope.CUSTOM_GROUPS
        tx.signers[0].allowed_groups = [keypair.public_key]

        engine.execute()
        self.assertEqual(vm.VMState.HALT, engine.state)
        self.assertEqual(1, len(engine.result_stack))
        item = engine.result_stack.pop()
        self.assertTrue(item.to_boolean())

        # now try again but make sure it fails if the public key is not listed in the allowed groups
        engine = test_engine(has_snapshot=True, default_script=False)
        tx = test_tx()
        engine.script_container = tx

        engine.snapshot.contracts.put(caller_contract)
        engine.snapshot.contracts.put(callee_contract)
        engine.load_script(vm.Script(caller_script))

        tx.signers[0].scope = payloads.WitnessScope.CUSTOM_GROUPS
        keypair = cryptography.KeyPair(private_key=b'\x02' * 32)
        tx.signers[0].allowed_groups = [keypair.public_key]

        engine.execute()
        self.assertEqual(vm.VMState.HALT, engine.state)
        self.assertEqual(1, len(engine.result_stack))
        item = engine.result_stack.pop()
        self.assertFalse(item.to_boolean())