示例#1
0
    def verify(self, snapshot: storage.Snapshot,
               tx: payloads.Transaction) -> bool:
        """
        Verifies the attribute with the transaction

        Returns:
            True if verification passes. False otherwise.
        """
        if any(
                map(lambda signer: signer.scope != payloads.WitnessScope.NONE,
                    tx.signers)):
            return False

        if tx.script != self._FIXED_ORACLE_SCRIPT:
            return False

        oracle = contracts.native.OracleContract()
        request = oracle.get_request(snapshot, self.id)
        if request is None:
            return False
        if tx.network_fee + tx.system_fee != request.gas_for_response:
            return False
        oracle_account = contracts.Contract.get_consensus_address(
            contracts.DesignationContract().get_designated_by_role(
                snapshot, contracts.DesignateRole.ORACLE,
                snapshot.best_block_height + 1))
        return any(
            map(lambda signer: signer.account == oracle_account, tx.signers))
示例#2
0
    def test_assign_and_get_role(self):
        engine = test_engine(has_snapshot=True, has_container=True)
        # set signers list to our committee to pass check_committee() validation
        engine.script_container.signers = [
            payloads.Signer(
                types.UInt160.from_string(
                    "54166e586e86b9d653bf96f61e6568df7a8ecb50"),
                payloads.WitnessScope.GLOBAL)
        ]
        public_key1 = cryptography.KeyPair(b'\x01' * 32).public_key
        public_key2 = cryptography.KeyPair(b'\x02' * 32).public_key
        public_key3 = cryptography.KeyPair(b'\x03' * 32).public_key
        c = contracts.DesignationContract()
        c.designate_as_role(engine, contracts.DesignateRole.STATE_VALIDATOR,
                            [public_key1, public_key2])
        c.designate_as_role(engine, contracts.DesignateRole.ORACLE,
                            [public_key3])

        index = engine.snapshot.persisting_block.index + 1
        state_nodes = c.get_designated_by_role(
            engine.snapshot, contracts.DesignateRole.STATE_VALIDATOR, index)
        self.assertEqual(2, len(state_nodes))
        self.assertIn(public_key1, state_nodes)
        self.assertIn(public_key2, state_nodes)

        oracle_nodes = c.get_designated_by_role(engine.snapshot,
                                                contracts.DesignateRole.ORACLE,
                                                index)
        self.assertEqual(1, len(oracle_nodes))
        self.assertEqual(public_key3, oracle_nodes[0])
示例#3
0
    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)
示例#4
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)