Exemple #1
0
    def current_scripthash(self) -> types.UInt160:
        """
        Get the script hash of the current executing smart contract

        Note: a smart contract can call other smart contracts.
        """
        return to_script_hash(self.current_context.script._value)
Exemple #2
0
    def post_persist(self, engine: contracts.ApplicationEngine):
        super(NeoToken, self).post_persist(engine)
        # distribute GAS for committee
        m = len(settings.standby_committee)
        n = settings.network.validators_count
        index = engine.snapshot.persisting_block.index % m
        gas_per_block = self.get_gas_per_block(engine.snapshot)
        committee = self.get_committee_from_cache(engine.snapshot)
        pubkey = committee[index]
        account = to_script_hash(contracts.Contract.create_signature_redeemscript(pubkey))
        GasToken().mint(engine, account, gas_per_block * self._COMMITTEE_REWARD_RATIO / 100, False)

        if self._should_refresh_committee(engine.snapshot.persisting_block.index):
            voter_reward_of_each_committee = gas_per_block * self._VOTER_REWARD_RATIO * 100000000 * m / (m + n) / 100
            for i, member in enumerate(committee):
                factor = 2 if i < n else 1
                member_votes = self._committee_state[member]
                if member_votes > 0:
                    voter_sum_reward_per_neo = voter_reward_of_each_committee * factor / member_votes
                    voter_reward_key = (self.key_voter_reward_per_committee
                                        + member
                                        + self._to_uint32(engine.snapshot.persisting_block.index + 1)
                                        )
                    border = (self.key_voter_reward_per_committee + member).to_array()
                    try:
                        pair = next(engine.snapshot.storages.find_range(voter_reward_key.to_array(), border, "reverse"))
                        result = vm.BigInteger(pair[1].value)
                    except StopIteration:
                        result = vm.BigInteger.zero()
                    voter_sum_reward_per_neo += result
                    engine.snapshot.storages.put(voter_reward_key,
                                                 storage.StorageItem(voter_sum_reward_per_neo.to_array()))
Exemple #3
0
 def get_committee_address(self,
                           snapshot: storage.Snapshot) -> types.UInt160:
     """ Get the script hash of the current committee """
     comittees = self.get_committee(snapshot)
     return to_script_hash(
         contracts.Contract.create_multisig_redeemscript(
             len(comittees) - (len(comittees) - 1) // 2, comittees))
Exemple #4
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)
Exemple #5
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)
Exemple #6
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)
Exemple #7
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())
Exemple #8
0
    def register_candidate(self, engine: contracts.ApplicationEngine,
                           public_key: cryptography.ECPoint) -> bool:
        """
        Register a candidate for consensus node election.

        Args:
            engine: Application engine instance
            public_key: the candidate's public key

        Returns:
            True is succesfully registered. False otherwise.
        """
        script_hash = to_script_hash(
            contracts.Contract.create_signature_redeemscript(public_key))
        if not engine.checkwitness(script_hash):
            return False

        engine.add_gas(self.get_register_price(engine.snapshot))
        storage_key = self.key_candidate + public_key
        storage_item = engine.snapshot.storages.try_get(storage_key,
                                                        read_only=False)
        if storage_item is None:
            state = _CandidateState()
            state.registered = True
            storage_item = storage.StorageItem(state.to_array())
            engine.snapshot.storages.put(storage_key, storage_item)
        else:
            state = storage_item.get(_CandidateState)
            state.registered = True
        self._candidates_dirty = True
        return True
Exemple #9
0
    def __init__(self,
                 password: str,
                 private_key: Optional[bytes] = None,
                 watch_only: bool = False,
                 address: Optional[str] = None,
                 label: Optional[str] = None,
                 lock: bool = False,
                 contract: Optional[contracts.Contract] = None,
                 extra: Optional[Dict[str, Any]] = None):
        """
        Instantiate an account. This constructor should only be directly called when it's desired to create a new
        account using just a password and a randomly generated private key, otherwise use the alternative constructors
        """
        public_key: Optional[cryptography.ECPoint] = None
        encrypted_key: Optional[bytes] = None
        contract_script: Optional[bytes] = None

        if watch_only:
            if address is None:
                raise ValueError(
                    "Creating a watch only account requires an address")
            else:
                self.validate_address(address)

        else:
            key_pair: cryptography.KeyPair

            if private_key is None:
                key_pair = cryptography.KeyPair.generate()
                private_key = key_pair.private_key
            else:
                key_pair = cryptography.KeyPair(private_key)
            encrypted_key = self.private_key_to_nep2(private_key, password)
            contract_script = contracts.Contract.create_signature_redeemscript(
                key_pair.public_key)
            script_hash = to_script_hash(contract_script)
            address = address if address else self.script_hash_to_address(
                script_hash)
            public_key = key_pair.public_key

        self.label: Optional[str] = label
        self.address: str = address
        self.public_key = public_key
        self.encrypted_key = encrypted_key
        self.lock = lock

        if not isinstance(contract, AccountContract):
            if contract is not None:
                contract = AccountContract.from_contract(contract)
            elif contract_script is not None:
                default_parameters_list = [
                    contracts.ContractParameterDefinition(
                        name='signature',
                        type=contracts.ContractParameterType.SIGNATURE)
                ]
                contract = AccountContract(contract_script,
                                           default_parameters_list)

        self.contract: Optional[AccountContract] = contract
        self.extra = extra if extra else {}
Exemple #10
0
    def unregister_candidate(self, engine: contracts.ApplicationEngine,
                             public_key: cryptography.ECPoint) -> bool:
        """
        Remove a candidate from the consensus node candidate list.
        Args:
            engine: Application engine instance
            public_key: the candidate's public key

        Returns:
            True is succesfully removed. False otherwise.

        """
        script_hash = to_script_hash(
            contracts.Contract.create_signature_redeemscript(public_key))
        if not engine.checkwitness(script_hash):
            return False

        storage_key = self.key_candidate + public_key
        storage_item = engine.snapshot.storages.try_get(storage_key,
                                                        read_only=False)
        if storage_item is None:
            return True
        else:
            state = storage_item.get(_CandidateState)
            state.registered = False
            if state.votes == 0:
                engine.snapshot.storages.delete(storage_key)

        self._candidates_dirty = True
        return True
Exemple #11
0
 def __init__(self, script: bytes,
              parameter_list: List[contracts.ContractParameterType]):
     #: The contract instructions (OpCodes)
     self.script = script
     self.parameter_list = parameter_list
     self._script_hash = to_script_hash(self.script)
     self._address = None
Exemple #12
0
    def entry_scripthash(self) -> types.UInt160:
        """
        Get the script hash of the first smart contract loaded into the engine

        Note: a smart contract can call other smart contracts.
        """
        return to_script_hash(self.entry_context.script._value)
Exemple #13
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())
    def load_context(self, context: vm.ExecutionContext) -> None:
        if len(context.scripthash_bytes) == 0:
            context.scripthash_bytes = to_script_hash(context.script._value).to_array()
        contract_hash = types.UInt160(data=context.scripthash_bytes)
        counter = self._invocation_counter.get(contract_hash, 0)
        self._invocation_counter.update({contract_hash: counter + 1})

        super(ApplicationEngine, self).load_context(context)
Exemple #15
0
    def test_checkwitness_called_by_entry(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,
                             has_container=False,
                             default_script=False)
        tx = test_tx()
        tx.signers[0].scope = payloads.WitnessScope.CALLED_BY_ENTRY
        engine.script_container = tx

        sb = vm.ScriptBuilder()
        sb.emit_push(tx.sender.to_array())
        sb.emit_syscall(syscall_name_to_int("System.Runtime.CheckWitness"))
        callee_contract_script = sb.to_array()
        callee_manifest = contracts.ContractManifest(
            contract_hash=to_script_hash(callee_contract_script))
        callee_manifest.abi.methods = [
            contracts.ContractMethodDescriptor(
                "test_func", 0, [], contracts.ContractParameterType.ANY)
        ]
        callee_contract = storage.ContractState(callee_contract_script,
                                                callee_manifest)

        sb = vm.ScriptBuilder()
        sb.emit(vm.OpCode.NEWARRAY0)  # args (empty array)
        sb.emit_push('test_func')  # target method name
        sb.emit_push(callee_contract.script_hash().to_array())  # contract hash
        sb.emit_syscall(syscall_name_to_int("System.Contract.Call"))
        caller_script = sb.to_array()
        caller_manifest = contracts.ContractManifest(
            contract_hash=to_script_hash(caller_script))
        caller_contract = storage.ContractState(caller_script, caller_manifest)

        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.assertTrue(item.to_boolean())
Exemple #16
0
 def on_persist(self, engine: contracts.ApplicationEngine) -> None:
     super(GasToken, self).on_persist(engine)
     total_network_fee = 0
     for tx in engine.snapshot.persisting_block.transactions:
         total_network_fee += tx.network_fee
         self.burn(engine, tx.sender, vm.BigInteger(tx.system_fee + tx.network_fee))
     pub_keys = NeoToken().get_next_block_validators(engine.snapshot)
     primary = pub_keys[engine.snapshot.persisting_block.primary_index]
     script_hash = to_script_hash(contracts.Contract.create_signature_redeemscript(primary))
     self.mint(engine, script_hash, vm.BigInteger(total_network_fee), False)
Exemple #17
0
 def get_script_hashes_for_verifying(
         self, snapshot: storage.Snapshot) -> List[types.UInt160]:
     validators = contracts.NeoToken().get_next_block_validators(snapshot)
     if len(validators) < self.validator_index:
         raise ValueError("Validator index is out of range")
     return [
         to_script_hash(
             contracts.Contract.create_signature_redeemscript(
                 validators[self.validator_index]))
     ]
Exemple #18
0
    def setUpClass(cls) -> None:
        settings.network.standby_committee = ['02158c4a4810fa2a6a12f7d33d835680429e1a68ae61161c5b3fbc98c7f1f17765']
        settings.network.validators_count = 1
        cls.validator_public_key = cryptography.ECPoint.deserialize_from_bytes(
            binascii.unhexlify(settings.network.standby_committee[0])
        )
        cls.validator_account = to_script_hash(
            contracts.Contract.create_multisig_redeemscript(1, [cls.validator_public_key]))

        blockchain.Blockchain()
Exemple #19
0
    def private_key_to_nep2(
            private_key: bytes,
            passphrase: str,
            scrypt_parameters: Optional[wallet.ScryptParameters] = None
    ) -> bytes:
        """
        Encrypt a private key into a nep2 key.

        Args:
            private_key: the key that will be encrypt.
            passphrase: the password to encrypt the nep2 key.
            scrypt_parameters: a ScryptParameters object that will be passed to the key derivation function.

        Returns:
            the encrypted nep2 key.
        """
        if scrypt_parameters is None:
            scrypt_parameters = wallet.ScryptParameters()

        key_pair = cryptography.KeyPair(private_key=private_key)
        script_hash = to_script_hash(
            contracts.Contract.create_signature_redeemscript(
                key_pair.public_key))
        address = Account.script_hash_to_address(script_hash)
        # NEP2 checksum: hash the address twice and get the first 4 bytes
        first_hash = hashlib.sha256(address.encode("utf-8")).digest()
        second_hash = hashlib.sha256(first_hash).digest()
        checksum = second_hash[:4]

        pwd_normalized = bytes(unicodedata.normalize("NFC", passphrase),
                               "utf-8")
        derived = hashlib.scrypt(password=pwd_normalized,
                                 salt=checksum,
                                 n=scrypt_parameters.n,
                                 r=scrypt_parameters.r,
                                 p=scrypt_parameters.p,
                                 dklen=64)

        derived1 = derived[:32]
        derived2 = derived[32:]

        xor_ed = Account._xor_bytes(bytes(private_key), derived1)
        cipher = AES.new(derived2, AES.MODE_ECB)
        encrypted = cipher.encrypt(xor_ed)

        nep2 = bytearray()
        nep2.extend(NEP_HEADER)
        nep2.extend(NEP_FLAG)
        nep2.extend(checksum)
        nep2.extend(encrypted)

        # Finally, encode with Base58Check
        encoded_nep2 = base58.b58encode_check(bytes(nep2))

        return encoded_nep2
Exemple #20
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_manifest = contracts.ContractManifest(
            contract_hash=to_script_hash(callee_contract_script))
        callee_manifest.abi.methods = [
            contracts.ContractMethodDescriptor(
                "test_func", 0, [], contracts.ContractParameterType.ANY)
        ]
        callee_contract = storage.ContractState(callee_contract_script,
                                                callee_manifest)

        # create caller_contract script
        sb = vm.ScriptBuilder()
        sb.emit(vm.OpCode.NEWARRAY0)  # args (empty array)
        sb.emit_push('test_func')  # target method name
        sb.emit_push(callee_contract.script_hash().to_array())  # contract hash
        sb.emit_syscall(syscall_name_to_int("System.Contract.Call"))
        caller_script = sb.to_array()
        caller_manifest = contracts.ContractManifest(
            contract_hash=to_script_hash(caller_script))
        caller_contract = storage.ContractState(caller_script, caller_manifest)

        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(caller_contract.script_hash().to_array(),
                         item.to_array())
Exemple #21
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_manifest = contracts.ContractManifest(
            contract_hash=to_script_hash(callee_contract_script))
        callee_manifest.abi.methods = [
            contracts.ContractMethodDescriptor(
                "test_func", 0, [], contracts.ContractParameterType.ANY)
        ]
        callee_contract = storage.ContractState(callee_contract_script,
                                                callee_manifest)

        sb = vm.ScriptBuilder()
        sb.emit(vm.OpCode.NEWARRAY0)  # args (empty array)
        sb.emit_push('test_func')  # target method name
        sb.emit_push(callee_contract.script_hash().to_array())  # contract hash
        sb.emit_syscall(syscall_name_to_int("System.Contract.Call"))
        caller_script = sb.to_array()
        caller_manifest = contracts.ContractManifest(
            contract_hash=to_script_hash(caller_script))
        caller_contract = storage.ContractState(caller_script, caller_manifest)

        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 #22
0
def do_checkwitness(engine: contracts.ApplicationEngine, data: bytes) -> bool:
    if len(data) == 20:
        hash_ = types.UInt160(data)
    elif len(data) == 33:
        redeemscript = contracts.Contract.create_signature_redeemscript(
            cryptography.ECPoint.deserialize_from_bytes(data))
        hash_ = to_script_hash(redeemscript)
    else:
        raise ValueError("Supplied CheckWitness data is not a valid hash")

    return engine.checkwitness(hash_)
Exemple #23
0
    def contract_create_with_data(
            self, engine: contracts.ApplicationEngine, nef_file: bytes,
            manifest: bytes, data: vm.StackItem) -> contracts.ContractState:
        if not isinstance(engine.script_container, payloads.Transaction):
            raise ValueError(
                "Cannot create contract without a Transaction script container"
            )

        nef_len = len(nef_file)
        manifest_len = len(manifest)
        if (nef_len == 0 or nef_len > engine.MAX_CONTRACT_LENGTH
                or manifest_len == 0
                or manifest_len > contracts.ContractManifest.MAX_LENGTH):
            raise ValueError("Invalid NEF or manifest length")

        engine.add_gas(
            max(engine.STORAGE_PRICE * (nef_len + manifest_len),
                self.get_minimum_deployment_fee(engine.snapshot)))

        nef = contracts.NEF.deserialize_from_bytes(nef_file)
        parsed_manifest = contracts.ContractManifest.from_json(
            json.loads(manifest.decode()))

        self.validate(nef.script, parsed_manifest.abi)

        sb = vm.ScriptBuilder()
        sb.emit(vm.OpCode.ABORT)
        sb.emit_push(engine.script_container.sender.to_array())
        sb.emit_push(nef.checksum)
        sb.emit_push(parsed_manifest.name)
        hash_ = to_script_hash(sb.to_array())

        existing_contract = engine.snapshot.contracts.try_get(hash_)
        if existing_contract is not None:
            raise ValueError("Contract already exists")

        contract = contracts.ContractState(
            self.get_next_available_id(engine.snapshot), nef, parsed_manifest,
            0, hash_)
        if not contract.manifest.is_valid(hash_):
            raise ValueError("Error: invalid manifest")
        engine.snapshot.contracts.put(contract)

        method_descriptor = contract.manifest.abi.get_method("_deploy", 2)
        if method_descriptor is not None:
            engine.call_from_native(self.hash, hash_, method_descriptor.name,
                                    [data, vm.BooleanStackItem(False)])

        msgrouter.interop_notify(
            self.hash, "Deploy",
            vm.ArrayStackItem(engine.reference_counter,
                              vm.ByteStringStackItem(
                                  contract.hash.to_array())))
        return contract
Exemple #24
0
 def setUp(self) -> None:
     self.RET = b'\x40'
     self.manifest = contracts.ContractManifest("contract_name")
     self.nef = contracts.NEF(script=self.RET)
     self.contract_hash = to_script_hash(self.nef.script)
     self.contract = contracts.ContractState(1, self.nef, self.manifest, 0,
                                             self.contract_hash)
     self.contract.manifest.abi.methods = [
         contracts.ContractMethodDescriptor(
             "test_func", 0, [], contracts.ContractParameterType.ANY, True)
     ]
 def test_contract_create_standard_account(self):
     keypair = cryptography.KeyPair(b'\x01' * 32)
     engine = test_engine()
     engine.push(vm.ByteStringStackItem(keypair.public_key.to_array()))
     engine.invoke_syscall_by_name("System.Contract.CreateStandardAccount")
     engine.execute()
     self.assertEqual(1, len(engine.result_stack))
     signature_redeem_script = contracts.Contract.create_signature_redeemscript(
         keypair.public_key)
     result_item = types.UInt160(engine.result_stack.pop().to_array())
     self.assertEqual(to_script_hash(signature_redeem_script), result_item)
Exemple #26
0
    def calling_scripthash(self) -> types.UInt160:
        """
        Get the script hash of the smart contract that called the current executing smart contract.

        Note: a smart contract can call other smart contracts.

        Raises:
            ValueError: if the current executing contract has not been called by another contract.
        """
        if len(self.current_context.calling_script) == 0:
            raise ValueError("Cannot retrieve calling script_hash - current context has not yet been called")
        return to_script_hash(self.current_context.calling_script._value)
    def init(self):
        self._methods: Dict[int, _NativeMethodMeta] = {}  # offset, meta

        self._management = contracts.ManagementContract()
        self._neo = contracts.NeoToken()
        self._gas = contracts.GasToken()
        self._policy = contracts.PolicyContract()
        self._oracle = contracts.OracleContract()
        self._ledger = contracts.LedgerContract()
        self._role = contracts.DesignationContract()
        self._crypto = contracts.CryptoContract()
        self._stdlib = contracts.StdLibContract()

        # Find all methods that have been augmented by the @register decorator
        # and turn them into methods that can be called by VM scripts
        methods_meta = []
        for pair in inspect.getmembers(self,
                                       lambda m: hasattr(m, "native_call")):
            methods_meta.append(_NativeMethodMeta(pair[1]))

        methods_meta.sort(
            key=lambda x: (x.descriptor.name, len(x.descriptor.parameters)))

        sb = vm.ScriptBuilder()
        for meta in methods_meta:
            meta.descriptor.offset = len(sb)
            sb.emit_push(0)
            self._methods.update({len(sb): meta})
            sb.emit_syscall(1736177434)  # "System.Contract.CallNative"
            sb.emit(vm.OpCode.RET)

        self._script: bytes = sb.to_array()
        self.nef = contracts.NEF("neo-core-v3.0", self._script)

        sender = types.UInt160.zero()  # OpCode.PUSH1
        sb = vm.ScriptBuilder()
        sb.emit(vm.OpCode.ABORT)
        sb.emit_push(sender.to_array())
        sb.emit_push(0)
        sb.emit_push(self.service_name())
        self._hash: types.UInt160 = to_script_hash(sb.to_array())
        self._manifest: contracts.ContractManifest = contracts.ContractManifest(
        )
        self._manifest.name = self.service_name()
        self._manifest.abi.methods = list(
            map(lambda m: m.descriptor, methods_meta))

        if self._id != NativeContract._id:
            self._contracts.update({self.service_name(): self})
            self._contract_hashes.update({self._hash: self})

        self.active_block_index = settings.native_contract_activation.get(
            self.service_name, 0)
Exemple #28
0
    def test_policy_block_account_and_is_blocked(self):
        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

        sb = vm.ScriptBuilder()

        # set or we won't pass the check_comittee() in the policy contract function implementations
        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]

        # first we setup the stack for calling `blockAccount`
        # push data to create a vm.Array holding 20 bytes for the UInt160 Account parameter of the _block_account function.
        sb.emit_push(b'\x11' * 20)
        sb.emit(vm.OpCode.PUSH1)
        sb.emit(vm.OpCode.PACK)
        sb.emit_push(15)  # call flags
        sb.emit_push("blockAccount")
        sb.emit_push(contracts.PolicyContract().hash.to_array())
        sb.emit_syscall(syscall_name_to_int("System.Contract.Call"))

        # next we call `isBlocked`
        sb.emit_push(b'\x11' * 20)
        sb.emit(vm.OpCode.PUSH1)
        sb.emit(vm.OpCode.PACK)
        sb.emit_push(15)  # call flags
        sb.emit_push("isBlocked")
        sb.emit_push(contracts.PolicyContract().hash.to_array())
        sb.emit_syscall(syscall_name_to_int("System.Contract.Call"))

        script = vm.Script(sb.to_array())
        engine.load_script(script)

        # storing the current script in a contract otherwise "System.Contract.Call" will fail its checks
        nef = contracts.NEF(script=sb.to_array())
        manifest = contracts.ContractManifest("test_contract")
        sender = engine.script_container.script_hashes[0]
        contract = contracts.ContractState(
            1, nef, manifest, 0,
            contract_hash(sender, nef.checksum, manifest.name))
        engine.snapshot.contracts.put(contract)

        engine.execute()
        self.assertEqual(vm.VMState.HALT, engine.state)
        self.assertEqual(2, len(engine.result_stack))
        get_is_blocked_result = engine.result_stack.pop()
        set_blocked_account_result = engine.result_stack.pop()
        self.assertTrue(set_blocked_account_result.to_boolean())
        self.assertTrue(get_is_blocked_result.to_boolean())
Exemple #29
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 #30
0
    def post_persist(self, engine: contracts.ApplicationEngine) -> None:
        super(OracleContract, self).post_persist(engine)
        nodes = []
        for tx in engine.snapshot.persisting_block.transactions:
            response = tx.try_get_attribute(payloads.OracleResponse)
            if response is None:
                continue

            # remove request from storage
            sk_request = self.key_request + response.id.to_bytes(8, 'little')
            si_request = engine.snapshot.storages.try_get(sk_request)
            if si_request is None:
                continue
            request = OracleRequest.deserialize_from_bytes(si_request.value)
            engine.snapshot.storages.delete(sk_request)

            # remove id from id list
            sk_id_list = self.key_id_list + self._get_url_hash(request.url)
            si_id_list = engine.snapshot.storages.try_get(sk_id_list,
                                                          read_only=False)
            if si_id_list is None:
                si_id_list = storage.StorageItem(b'\x00')

            id_list = si_id_list.get(_IdList)
            id_list.remove(response.id)
            if len(id_list) == 0:
                engine.snapshot.storages.delete(sk_id_list)

            # mint gas for oracle nodes
            nodes_public_keys = contracts.DesignationContract(
            ).get_designated_by_role(engine.snapshot,
                                     contracts.DesignateRole.ORACLE,
                                     engine.snapshot.persisting_block.index)

            for public_key in nodes_public_keys:
                nodes.append([
                    to_script_hash(
                        contracts.Contract.create_signature_redeemscript(
                            public_key)),
                    vm.BigInteger.zero()
                ])
            if len(nodes) > 0:
                idx = response.id % len(nodes)
                # mypy can't figure out that the second item is a BigInteger
                nodes[idx][1] += self.get_price(
                    engine.snapshot)  # type: ignore

        for pair in nodes:
            if pair[1].sign > 0:  # type: ignore
                self._gas.mint(engine, pair[0], pair[1], False)