Пример #1
0
    def ScriptHash(self):

        if self._scriptHash is None:
            try:
                self._scriptHash = Crypto.ToScriptHash(self.Script)
            except binascii.Error:
                self._scriptHash = Crypto.ToScriptHash(self.Script, unhex=False)
            except Exception as e:
                logger.error("Could not create script hash: %s " % e)

        return self._scriptHash
Пример #2
0
async def verify_signature(message):
    """ Verifies a signature of a message, return True if verified, false if not
    """
    Crypto.SetupSignatureCurve()

    try:
        signature = json.loads(message['signature'])
    except Exception:
        LOGGER.exception("NEO Signature deserialization error")
        return False

    try:
        script_hash = Crypto.ToScriptHash("21" + signature['publicKey'] + "ac")
        address = Crypto.ToAddress(script_hash)
    except Exception:
        LOGGER.exception("NEO Signature Key error")
        return False

    if address != message['sender']:
        LOGGER.warning('Received bad signature from %s for %s' %
                       (address, message['sender']))
        return False

    try:
        verification = await buildNEOVerification(message, signature['salt'])

        result = Crypto.VerifySignature(verification,
                                        bytes.fromhex(signature['data']),
                                        bytes.fromhex(signature['publicKey']),
                                        unhex=True)
    except Exception:
        LOGGER.exception("NULS Signature verification error")
        result = False

    return result
Пример #3
0
    def GenesisBlock() -> Block:
        """
        Create the GenesisBlock.

        Returns:
            BLock:
        """
        prev_hash = UInt256(data=bytearray(32))
        timestamp = int(
            datetime(2016, 7, 15, 15, 8, 21, tzinfo=pytz.utc).timestamp())
        index = 0
        consensus_data = 2083236893  # Pay tribute To Bitcoin
        next_consensus = Blockchain.GetConsensusAddress(
            Blockchain.StandbyValidators())
        script = Witness(bytearray(0), bytearray(PUSHT))

        mt = MinerTransaction()
        mt.Nonce = 2083236893

        output = TransactionOutput(
            Blockchain.SystemShare().Hash,
            Blockchain.SystemShare().Amount,
            Crypto.ToScriptHash(
                Contract.CreateMultiSigRedeemScript(
                    int(len(Blockchain.StandbyValidators()) / 2) + 1,
                    Blockchain.StandbyValidators())))

        it = IssueTransaction([], [output], [], [script])

        return Block(
            prev_hash, timestamp, index, consensus_data, next_consensus,
            script,
            [mt, Blockchain.SystemShare(),
             Blockchain.SystemCoin(), it], True)
Пример #4
0
    def IsWalletTransaction(self, tx):
        """
        Verifies if a transaction belongs to the wallet.

        Args:
            tx (TransactionOutput):an instance of type neo.Core.TX.Transaction.TransactionOutput to verify.

        Returns:
            bool: True, if transaction belongs to wallet. False, if not.
        """
        for key, contract in self._contracts.items():

            for output in tx.outputs:
                if output.ScriptHash.ToBytes() == contract.ScriptHash.ToBytes(
                ):
                    return True

            for script in tx.scripts:

                if script.VerificationScript:
                    if bytes(contract.Script) == script.VerificationScript:
                        return True

        for watch_script_hash in self._watch_only:
            for output in tx.outputs:
                if output.ScriptHash == watch_script_hash:
                    return True
            for script in tx.scripts:
                if Crypto.ToScriptHash(script.VerificationScript,
                                       unhex=False) == watch_script_hash:
                    return True

        return False
Пример #5
0
    def execute(self, arguments):
        wallet = PromptData.Wallet

        if len(arguments) < 3:
            print("Please specify the minimum required parameters")
            return False

        pubkey_in_wallet = arguments[0]
        if not PromptUtils.is_valid_public_key(pubkey_in_wallet):
            print("Invalid public key format")
            return False

        key_script_hash = Crypto.ToScriptHash(pubkey_in_wallet, unhex=True)
        if not wallet.ContainsKeyHash(key_script_hash):
            print("Supplied first public key does not exist in own wallet.")
            return False

        try:
            min_signature_cnt = int(arguments[1])
        except ValueError:
            print(f"Invalid minimum signature count value: {arguments[1]}")
            return False

        if min_signature_cnt < 1:
            print("Minimum signatures count cannot be lower than 1")
            return False

        # validate minimum required signing key count
        signing_keys = arguments[2:]
        signing_keys.append(pubkey_in_wallet)
        len_signing_keys = len(signing_keys)
        if len_signing_keys < min_signature_cnt:
            # we need at least 2 public keys in total otherwise it's just a regular address.
            # 1 pub key is from an address in our own wallet, a secondary key can come from any place.
            print(
                f"Missing remaining signing keys. Minimum required: {min_signature_cnt} given: {len_signing_keys}"
            )
            return False

        # validate remaining pub keys
        for key in signing_keys:
            if not PromptUtils.is_valid_public_key(key):
                print(f"Invalid signing key {key}")
                return False

        # validate that all signing keys are unique
        if len(signing_keys) > len(set(signing_keys)):
            print("Provided signing keys are not unique")
            return False

        verification_contract = Contract.CreateMultiSigContract(
            key_script_hash, min_signature_cnt, signing_keys)
        address = verification_contract.Address
        wallet.AddContract(verification_contract)
        print(f"Added multi-sig contract address {address} to wallet")
        return True
Пример #6
0
def is_valid_public_key(key):
    if len(key) != 66:
        return False
    try:
        Crypto.ToScriptHash(key, unhex=True)
    except Exception:
        # the UINT160 inside ToScriptHash can throw Exception
        return False
    else:
        return True
Пример #7
0
    def GetAddress(self):
        """
        Returns the public NEO address for this KeyPair

        Returns:
            str: The private key
        """
        script = b'21' + self.PublicKey.encode_point(True) + b'ac'
        script_hash = Crypto.ToScriptHash(script)
        address = Crypto.ToAddress(script_hash)
        return address
Пример #8
0
    def ScriptHash(self):
        """
        Get the script hash.

        Returns:
            UInt160:
        """
        if self._scriptHash is None:
            self._scriptHash = Crypto.ToScriptHash(self.Script, unhex=False)

        return self._scriptHash
Пример #9
0
    def ContainsKey(self, public_key):
        """
        Test if the wallet contains the supplied public key.

        Args:
            public_key (edcsa.Curve.point): a public key to test for its existance. e.g. KeyPair.PublicKey

        Returns:
            bool: True if exists, False otherwise.
        """
        return self.ContainsKeyHash(
            Crypto.ToScriptHash(public_key.encode_point(True), unhex=True))
Пример #10
0
    def GetConsensusAddress(validators):
        """
        Get the script hash of the consensus node.

        Args:
            validators (list): of Ellipticcurve.ECPoint's

        Returns:
            UInt160:
        """
        vlen = len(validators)
        script = Contract.CreateMultiSigRedeemScript(
            vlen - int((vlen - 1) / 3), validators)
        return Crypto.ToScriptHash(script)
Пример #11
0
    def Sign(self, NEP2orPrivateKey, NEP2password=None, multisig_args=[]):
        """
        Sign the raw transaction

        Args:
            NEP2orPrivateKey: (str) the NEP2 or PrivateKey string from the address you are sending from. NOTE: Assumes WIF if NEP2password is None.
            NEP2password: (str, optional) the NEP2 password associated with the NEP2 key string. Defaults to None.
            multisig_args: (list, optional) the arguments for importing a multsig address (e.g. [<owner pubkey>, <num required sigs>, [<signing pubkey>, ...]])
        """
        temp_path = "temp_wallet.wallet"
        temp_password = "******"
        wallet = UserWallet.Create(temp_path,
                                   to_aes_key(temp_password),
                                   generate_default_key=False)
        if NEP2password:
            private_key = KeyPair.PrivateKeyFromNEP2(NEP2orWIF, NEP2password)
        else:
            private_key = binascii.unhexlify(NEP2orPrivateKey)
        wallet.CreateKey(private_key)

        if multisig_args:  # import a multisig address
            verification_contract = Contract.CreateMultiSigContract(
                Crypto.ToScriptHash(multisig_args[0], unhex=True),
                multisig_args[1], multisig_args[2])
            wallet.AddContract(verification_contract)

        if self.Type == b'\xd1' and not self.SOURCE_SCRIPTHASH:  # in case of an invocation with no funds transfer
            context = ContractParametersContext(self)
        elif not self._context:  # used during transactions involving a funds transfer
            signer_contract = wallet.GetContract(self.SOURCE_SCRIPTHASH)
            context = ContractParametersContext(
                self, isMultiSig=signer_contract.IsMultiSigContract)
        else:
            context = self._context  # used for a follow-on signature for a multi-sig transaction

        wallet.Sign(context)
        if context.Completed:
            self.scripts = context.GetScripts()
            self.Validate()  # ensure the tx is ready to be relayed
        elif context.ContextItems:
            self._context = context
            print(
                "Transaction initiated, but the signature is incomplete. Sign again with another valid multi-sig keypair."
            )
        else:
            raise SignatureError("Unable to sign transaction.")
        wallet.Close()
        wallet = None
        os.remove(temp_path)
Пример #12
0
    def __init__(self, priv_key):
        """
        Create an instance.

        Args:
            priv_key (bytes): a private key.

        Raises:
            ValueError:
                if the input `priv_key` length is not 32, 96, or 104
                if the input `priv_key` length is 32 but the public key still could not be determined
        """
        self.setup_curve()
        self.PublicKeyHash = None
        self.PublicKey = None
        self.PrivateKey = None

        length = len(priv_key)

        if length != 32 and length != 96 and length != 104:
            raise ValueError("Invalid private key")

        self.PrivateKey = bytearray(priv_key[-32:])

        pubkey_encoded_not_compressed = None

        if length == 32:
            try:
                pubkey_encoded_not_compressed = bitcoin.privkey_to_pubkey(
                    priv_key)
            except Exception:
                raise ValueError("Could not determine public key")

        elif length == 96 or length == 104:
            skip = length - 96
            pubkey_encoded_not_compressed = bytearray(b'\x04') + bytearray(
                priv_key[skip:skip + 64])

        if pubkey_encoded_not_compressed:
            pubkey_points = bitcoin.decode_pubkey(
                pubkey_encoded_not_compressed, 'bin')

            pubx = pubkey_points[0]
            puby = pubkey_points[1]
            edcsa = ECDSA.secp256r1()
            self.PublicKey = edcsa.Curve.point(pubx, puby)

        self.PublicKeyHash = Crypto.ToScriptHash(
            self.PublicKey.encode_point(True), unhex=True)
Пример #13
0
    def SystemShare():
        """
        Register AntShare.

        Returns:
            RegisterTransaction:
        """
        amount = Fixed8.FromDecimal(
            sum(Blockchain.GENERATION_AMOUNT) * Blockchain.DECREMENT_INTERVAL)
        owner = ECDSA.secp256r1().Curve.Infinity
        admin = Crypto.ToScriptHash(PUSHT)
        return RegisterTransaction(
            [], [], AssetType.GoverningToken,
            "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]",
            amount, 0, owner, admin)
Пример #14
0
    def CreateSignatureContract(publicKey):
        """
        Create a signature contract.

        Args:
            publicKey (edcsa.Curve.point): e.g. KeyPair.PublicKey.

        Returns:
            neo.SmartContract.Contract: a Contract instance.
        """
        script = Contract.CreateSignatureRedeemScript(publicKey)
        params = b'\x00'
        encoded = publicKey.encode_point(True)
        pubkey_hash = Crypto.ToScriptHash(encoded, unhex=True)

        return Contract(script, params, pubkey_hash)
Пример #15
0
    def SystemCoin():
        """
        Register AntCoin

        Returns:
            RegisterTransaction:
        """
        amount = Fixed8.FromDecimal(
            sum(Blockchain.GENERATION_AMOUNT) * Blockchain.DECREMENT_INTERVAL)

        owner = ECDSA.secp256r1().Curve.Infinity

        precision = 8
        admin = Crypto.ToScriptHash(PUSHF)

        return RegisterTransaction(
            [], [], AssetType.UtilityToken,
            "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
            amount, precision, owner, admin)
Пример #16
0
    def execute(self, arguments):
        wallet = PromptData.Wallet

        if len(arguments) != 2:
            print("Please specify the required parameters")
            return

        try:
            contract_hash = UInt160.ParseString(arguments[0]).ToBytes()
        except Exception:
            print(f"Invalid contract hash: {arguments[0]}")
            return

        pubkey = arguments[1]
        if not PromptUtils.is_valid_public_key(pubkey):
            print(f"Invalid pubkey: {arguments[1]}")
            return

        pubkey_script_hash = Crypto.ToScriptHash(pubkey, unhex=True)

        return ImportContractAddr(wallet, contract_hash, pubkey_script_hash)
Пример #17
0
    def test_issue_tx(self):

        miner_tx = MinerTransaction()
        miner_tx.Nonce = 2083236893

        share_tx = GetSystemShare()
        coin_tx = GetSystemCoin()

        script = Contract.CreateMultiSigRedeemScript(
            int(len(Blockchain.StandbyValidators()) / 2) + 1,
            Blockchain.StandbyValidators())

        if settings.MAGIC == 1953787457:
            self.assertEqual(script, self.contractraw)
            out = Crypto.ToScriptHash(script)

            output = TransactionOutput(share_tx.Hash,
                                       Blockchain.SystemShare().Amount, out)

            script = Witness(bytearray(0), bytearray(PUSHT))

            issue_tx = IssueTransaction([], [output], [], [script])
            self.assertEqual(issue_tx.GetHashData(), self.issuetx_rraw)
            self.assertEqual(issue_tx.Hash.ToBytes(), self.gen_issue_tx_id)
Пример #18
0
def test_deploy_and_invoke(deploy_script,
                           invoke_args,
                           wallet,
                           from_addr=None,
                           min_fee=DEFAULT_MIN_FEE,
                           invocation_test_mode=True,
                           debug_map=None,
                           invoke_attrs=None,
                           owners=None):
    bc = GetBlockchain()

    accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState)
    contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, DBPrefix.ST_Storage, StorageItem)

    if settings.USE_DEBUG_STORAGE:
        debug_storage = DebugStorage.instance()
        storages = DBCollection(debug_storage.db, DBPrefix.ST_Storage,
                                StorageItem)
        storages.DebugStorage = True

    dtx = InvocationTransaction()
    dtx.Version = 1
    dtx.outputs = []
    dtx.inputs = []
    dtx.scripts = []
    dtx.Script = binascii.unhexlify(deploy_script)

    if from_addr is not None:
        from_addr = PromptUtils.lookup_addr_str(wallet, from_addr)

    try:
        dtx = wallet.MakeTransaction(tx=dtx, from_addr=from_addr)
    except (ValueError, TXFeeError):
        pass

    context = ContractParametersContext(dtx)
    wallet.Sign(context)
    dtx.scripts = context.GetScripts()

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    contract = wallet.GetDefaultContract()
    dtx.Attributes = [
        TransactionAttribute(usage=TransactionAttributeUsage.Script,
                             data=Crypto.ToScriptHash(contract.Script,
                                                      unhex=False))
    ]
    dtx.Attributes = make_unique_script_attr(dtx.Attributes)

    to_dispatch = []

    engine = ApplicationEngine(trigger_type=TriggerType.Application,
                               container=dtx,
                               table=script_table,
                               service=service,
                               gas=dtx.Gas,
                               testMode=True)

    engine.LoadScript(dtx.Script)

    # first we will execute the test deploy
    # then right after, we execute the test invoke

    d_success = engine.Execute()

    if d_success:

        items = engine.ResultStack.Items

        contract_state = None
        for i in items:
            if type(i) is ContractState:
                contract_state = i
                break
            elif type(i) is InteropInterface:
                item = i.GetInterface()
                if type(item) is ContractState:
                    contract_state = item
                    break

        shash = contract_state.Code.ScriptHash()

        invoke_args, neo_to_attach, gas_to_attach = PromptUtils.get_asset_attachments(
            invoke_args)
        invoke_args, no_parse_addresses = PromptUtils.get_parse_addresses(
            invoke_args)

        invoke_args.reverse()

        if '--i' in invoke_args:
            invoke_args = []
            for index, iarg in enumerate(contract_state.Code.ParameterList):
                param, abort = PromptUtils.gather_param(index, iarg)
                if abort:
                    return None, [], 0, None
                else:
                    invoke_args.append(param)
            invoke_args.reverse()

        sb = ScriptBuilder()

        for p in invoke_args:
            item = PromptUtils.parse_param(p,
                                           wallet,
                                           parse_addr=no_parse_addresses)
            if type(item) is list:
                item.reverse()
                listlength = len(item)
                for listitem in item:
                    subitem = PromptUtils.parse_param(
                        listitem, wallet, parse_addr=no_parse_addresses)
                    if type(subitem) is list:
                        subitem.reverse()
                        for listitem2 in subitem:
                            subsub = PromptUtils.parse_param(
                                listitem2,
                                wallet,
                                parse_addr=no_parse_addresses)
                            sb.push(subsub)
                        sb.push(len(subitem))
                        sb.Emit(PACK)
                    else:
                        sb.push(subitem)

                sb.push(listlength)
                sb.Emit(PACK)
            else:
                sb.push(item)

        sb.EmitAppCall(shash.Data)
        out = sb.ToArray()

        outputs = []

        if neo_to_attach:
            output = TransactionOutput(
                AssetId=Blockchain.SystemShare().Hash,
                Value=neo_to_attach,
                script_hash=contract_state.Code.ScriptHash(),
            )
            outputs.append(output)

        if gas_to_attach:
            output = TransactionOutput(
                AssetId=Blockchain.SystemCoin().Hash,
                Value=gas_to_attach,
                script_hash=contract_state.Code.ScriptHash())

            outputs.append(output)

        itx = InvocationTransaction()
        itx.Version = 1
        itx.outputs = outputs
        itx.inputs = []
        itx.scripts = []
        itx.Attributes = deepcopy(invoke_attrs) if invoke_attrs else []
        itx.Script = binascii.unhexlify(out)

        if len(outputs) < 1 and not owners:
            contract = wallet.GetDefaultContract()
            itx.Attributes.append(
                TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                     data=contract.ScriptHash))
            itx.Attributes = make_unique_script_attr(itx.Attributes)

        try:
            itx = wallet.MakeTransaction(tx=itx, from_addr=from_addr)
        except (ValueError, TXFeeError):
            pass

        context = ContractParametersContext(itx)
        wallet.Sign(context)

        if owners:
            owners = list(owners)
            for owner in owners:
                itx.Attributes.append(
                    TransactionAttribute(
                        usage=TransactionAttributeUsage.Script, data=owner))
                itx.Attributes = make_unique_script_attr(itx.Attributes)
            context = ContractParametersContext(itx, isMultiSig=True)

        if context.Completed:
            itx.scripts = context.GetScripts()
        else:
            logger.warn(
                "Not gathering signatures for test build.  For a non-test invoke that would occur here."
            )
        #            if not gather_signatures(context, itx, owners):
        #                return None, [], 0, None

        #        print("gathered signatures %s " % itx.scripts)

        engine = ApplicationEngine(trigger_type=TriggerType.Application,
                                   container=itx,
                                   table=script_table,
                                   service=service,
                                   gas=itx.Gas,
                                   testMode=invocation_test_mode)

        engine.invocation_args = invoke_args
        engine.LoadScript(itx.Script)
        engine.LoadDebugInfoForScriptHash(debug_map, shash.Data)

        i_success = engine.Execute()

        service.ExecutionCompleted(engine, i_success)
        to_dispatch = to_dispatch + service.events_to_dispatch

        for event in to_dispatch:
            events.emit(event.event_type, event)

        if i_success:
            service.TestCommit()
            if len(service.notifications) > 0:

                for n in service.notifications:
                    Blockchain.Default().OnNotify(n)

            logger.info("Used %s Gas " % engine.GasConsumed().ToString())

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed = consumed.Ceil()

            if consumed <= Fixed8.Zero():
                consumed = min_fee

            total_ops = engine.ops_processed

            # set the amount of gas the tx will need
            itx.Gas = consumed
            itx.Attributes = []
            result = engine.ResultStack.Items
            return itx, result, total_ops, engine
        else:
            print("error executing invoke contract...")

    else:
        print("error executing deploy contract.....")

    service.ExecutionCompleted(engine, False, 'error')

    return None, [], 0, None
Пример #19
0
    def Contract_Create(self, engine: ExecutionEngine):

        script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(script) > 1024 * 1024:
            return False

        param_list = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()
        if len(param_list) > 252:
            return False
        return_type = int(
            engine.CurrentContext.EvaluationStack.Pop().GetBigInteger())
        if return_type < 0 or return_type > 0xff:
            raise ValueError("Invalid return type data popped from stack")

        contract_properties = int(
            engine.CurrentContext.EvaluationStack.Pop().GetBigInteger())

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        name = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        code_version = engine.CurrentContext.EvaluationStack.Pop(
        ).GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        author = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        email = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 65536:
            return False

        description = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        )

        hash = Crypto.ToScriptHash(script, unhex=False)

        contract = self.Snapshot.Contracts.TryGet(hash.ToBytes())

        if contract is None:
            try:
                code = FunctionCode(script=script,
                                    param_list=param_list,
                                    return_type=return_type,
                                    contract_properties=contract_properties)
            except ValueError:
                # exception is caused by an invalid `return_type`. neo-cli accepts this , but we throw an exception
                # this is a dirty hack to work around the VM state difference that it causes until neo-cli hopefully fixes it
                # see https://github.com/neo-project/neo/issues/827
                code = FunctionCode(script=script,
                                    param_list=param_list,
                                    contract_properties=contract_properties)
                code.ReturnType = return_type

            contract = ContractState(code, contract_properties, name,
                                     code_version, author, email, description)

            self.Snapshot.Contracts.Add(code.ScriptHash().ToBytes(), contract)

            self._contracts_created[hash.ToBytes()] = UInt160(
                data=engine.CurrentContext.ScriptHash())

        engine.CurrentContext.EvaluationStack.PushT(
            StackItem.FromInterface(contract))

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.CONTRACT_CREATED,
                               ContractParameter(
                                   ContractParameterType.InteropInterface,
                                   contract),
                               hash,
                               GetBlockchain().Height + 1,
                               engine.ScriptContainer.Hash
                               if engine.ScriptContainer else None,
                               test_mode=engine.testMode))
        return True
Пример #20
0
    def VerifyWitnesses(verifiable, snapshot):
        """
        Verify the scripts of the provided `verifiable` object.

        Args:
            verifiable (neo.IO.Mixins.VerifiableMixin):

        Returns:
            bool: True if verification is successful. False otherwise.
        """
        try:
            hashes = verifiable.GetScriptHashesForVerifying(snapshot)
        except Exception as e:
            logger.debug("couldn't get script hashes %s " % e)
            return False

        if len(hashes) != len(verifiable.Scripts):
            logger.debug(f"hash - verification script length mismatch ({len(hashes)}/{len(verifiable.Scripts)})")
            return False

        blockchain = GetBlockchain()

        for i in range(0, len(hashes)):
            verification = verifiable.Scripts[i].VerificationScript

            if len(verification) == 0:
                sb = ScriptBuilder()
                sb.EmitAppCall(hashes[i].Data)
                verification = sb.ms.getvalue()
                sb.ms.Cleanup()
            else:
                verification_hash = Crypto.ToScriptHash(verification, unhex=False)
                if hashes[i] != verification_hash:
                    logger.debug(f"hash {hashes[i]} does not match verification hash {verification_hash}")
                    return False

            engine = neo.SmartContract.ApplicationEngine.ApplicationEngine(TriggerType.Verification, verifiable, snapshot, Fixed8.Zero())
            engine.LoadScript(verification)
            invocation = verifiable.Scripts[i].InvocationScript
            engine.LoadScript(invocation)

            try:
                success = engine.Execute()
                engine._Service.ExecutionCompleted(engine, success)
            except Exception as e:
                engine._Service.ExecutionCompleted(engine, False, e)

            if engine.ResultStack.Count != 1 or not engine.ResultStack.Pop().GetBoolean():
                for event in engine._Service.events_to_dispatch:
                    events.emit(event.event_type, event)

                if engine.ResultStack.Count > 0:
                    logger.debug(
                        f"Result stack failure! Count: {engine.ResultStack.Count} bool value: {engine.ResultStack.Pop().GetBoolean()}")
                else:
                    logger.debug(f"Result stack failure! Count: {engine.ResultStack.Count}")
                return False

            for event in engine._Service.events_to_dispatch:
                events.emit(event.event_type, event)

        return True
Пример #21
0
    def test_gather_param(self):
        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value='hello') as fake_prompt:
            result, abort = Utils.gather_param(0, ContractParameterType.String)

            self.assertEqual(result, 'hello')

        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value=1) as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.Integer)

            self.assertEqual(result, 1)

        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value='1') as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.Integer)

            self.assertEqual(result, 1)

        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value=1.03) as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.Integer)

            self.assertEqual(result, 1)

        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value="bytearray(b'abc')") as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.ByteArray)

            self.assertEqual(result, bytearray(b'abc'))

        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value="b'abc'") as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.ByteArray)

            self.assertEqual(result, bytearray(b'abc'))

        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value="abc") as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.Boolean)

            self.assertEqual(result, True)

        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value=0) as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.Boolean)

            self.assertEqual(result, False)

        # test ContractParameterType.ByteArray for address input
        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value='AeV59NyZtgj5AMQ7vY6yhr2MRvcfFeLWSb'
                        ) as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.ByteArray)

            self.assertEqual(
                result,
                bytearray(
                    b'\xf9\x1dkp\x85\xdb|Z\xaf\t\xf1\x9e\xee\xc1\xca<\r\xb2\xc6\xec'
                ))

        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value='["a","b","c"]') as fake_prompt:
            result, abort = Utils.gather_param(0, ContractParameterType.Array)

            self.assertEqual(result, ['a', 'b', 'c'])

        with mock.patch(
                'neo.Prompt.Utils.get_input_prompt',
                return_value='["a","b","c", [1, 3, 4], "e"]') as fake_prompt:
            result, abort = Utils.gather_param(0, ContractParameterType.Array)

            self.assertEqual(result, ['a', 'b', 'c', [1, 3, 4], 'e'])

        # test ContractParameterType.Array without a closed list
        with mock.patch(
                'neo.Prompt.Utils.get_input_prompt',
                return_value='["a","b","c", [1, 3, 4], "e"') as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.Array,
                                               do_continue=False)

            self.assertEqual(result, None)
            self.assertEqual(abort, True)

        # test ContractParameterType.Array with no list
        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value="b'abc'") as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.Array,
                                               do_continue=False)

            self.assertRaises(Exception, "Please provide a list")
            self.assertEqual(result, None)
            self.assertEqual(abort, True)

        # test ContractParameterType.PublicKey
        with mock.patch(
                'neo.Prompt.Utils.get_input_prompt',
                return_value=
                "03cbb45da6072c14761c9da545749d9cfd863f860c351066d16df480602a2024c6"
        ) as fake_prompt:
            test_wallet_path = shutil.copyfile(
                WalletFixtureTestCase.wallet_1_path(),
                WalletFixtureTestCase.wallet_1_dest())
            wallet = UserWallet.Open(
                test_wallet_path,
                to_aes_key(WalletFixtureTestCase.wallet_1_pass()))

            addr_scripthash = wallet.GetStandardAddress()

            result, abort = Utils.gather_param(0,
                                               ContractParameterType.PublicKey)

            script = b'21' + result.encode_point(True) + b'ac'
            pk_script_hash = Crypto.ToScriptHash(script)

            self.assertEqual(
                addr_scripthash, pk_script_hash
            )  # verifies the functionality of ContractParameterType.PublicKey

            wallet.Close()
            wallet = None
            os.remove(WalletFixtureTestCase.wallet_1_dest())

        # test ContractParameterType.PublicKey with bad public key
        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value="blah") as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.PublicKey)
            self.assertIsNone(result)
            self.assertTrue(abort)

        # test unknown ContractParameterType
        with mock.patch('neo.Prompt.Utils.get_input_prompt',
                        return_value="9698b1cac6ce9cbe8517e490778525b929e01903"
                        ) as fake_prompt:
            result, abort = Utils.gather_param(0,
                                               ContractParameterType.Hash160,
                                               do_continue=False)

            self.assertRaises(Exception, "Unknown param type Hash160")
            self.assertEqual(result, None)
            self.assertEqual(abort, True)

        # test Exception
        with mock.patch('sys.stdout', new=StringIO()) as mock_print:
            with mock.patch(
                    'neo.Prompt.Utils.get_input_prompt') as fake_prompt:
                fake_prompt.side_effect = [
                    Exception(-32602, "Invalid params"), KeyboardInterrupt
                ]

                result, abort = Utils.gather_param(
                    0, ContractParameterType.String)

                self.assertEqual(result, None)
                self.assertEqual(abort, True)
                self.assertIn("Invalid params", mock_print.getvalue())

        # test KeyboardInterrupt
        with mock.patch('sys.stdout', new=StringIO()) as mock_print:
            with mock.patch(
                    'neo.Prompt.Utils.get_input_prompt') as fake_prompt:
                fake_prompt.side_effect = [KeyboardInterrupt]

                result, abort = Utils.gather_param(
                    0, ContractParameterType.String)

                self.assertEqual(result, None)
                self.assertEqual(abort, True)
                self.assertIn("Input cancelled", mock_print.getvalue())
Пример #22
0
    def VerifyScripts(verifiable):
        """
        Verify the scripts of the provided `verifiable` object.

        Args:
            verifiable (neo.IO.Mixins.VerifiableMixin):

        Returns:
            bool: True if verification is successful. False otherwise.
        """
        try:
            hashes = verifiable.GetScriptHashesForVerifying()
        except Exception as e:
            logger.debug("couldn't get script hashes %s " % e)
            return False

        if len(hashes) != len(verifiable.Scripts):
            logger.debug(
                f"hash - verification script length mismatch ({len(hashes)}/{len(verifiable.Scripts)})"
            )
            return False

        blockchain = GetBlockchain()

        for i in range(0, len(hashes)):
            verification = verifiable.Scripts[i].VerificationScript

            if len(verification) == 0:
                sb = ScriptBuilder()
                sb.EmitAppCall(hashes[i].Data)
                verification = sb.ms.getvalue()
            else:
                verification_hash = Crypto.ToScriptHash(verification,
                                                        unhex=False)
                if hashes[i] != verification_hash:
                    logger.debug(
                        f"hash {hashes[i]} does not match verification hash {verification_hash}"
                    )
                    return False

            state_reader = GetStateReader()
            script_table = CachedScriptTable(
                DBCollection(blockchain._db, DBPrefix.ST_Contract,
                             ContractState))

            engine = ApplicationEngine(TriggerType.Verification,
                                       verifiable, script_table, state_reader,
                                       Fixed8.Zero())
            engine.LoadScript(verification)
            invocation = verifiable.Scripts[i].InvocationScript
            engine.LoadScript(invocation)

            try:
                success = engine.Execute()
                state_reader.ExecutionCompleted(engine, success)
            except Exception as e:
                state_reader.ExecutionCompleted(engine, False, e)

            if engine.ResultStack.Count != 1 or not engine.ResultStack.Pop(
            ).GetBoolean():
                Helper.EmitServiceEvents(state_reader)
                if engine.ResultStack.Count > 0:
                    logger.debug(
                        f"Result stack failure! Count: {engine.ResultStack.Count} bool value: {engine.ResultStack.Pop().GetBoolean()}"
                    )
                else:
                    logger.debug(
                        f"Result stack failure! Count: {engine.ResultStack.Count}"
                    )
                return False

            Helper.EmitServiceEvents(state_reader)

        return True
Пример #23
0
def test_deploy_and_invoke(deploy_script, invoke_args, wallet,
                           from_addr=None, min_fee=DEFAULT_MIN_FEE, invocation_test_mode=True,
                           debug_map=None, invoke_attrs=None, owners=None, enable_debugger=False, snapshot=None):

    if settings.USE_DEBUG_STORAGE:
        debug_storage = DebugStorage.instance()
        storages = DBInterface(debug_storage.db, DBPrefix.ST_Storage, StorageItem)
        storages.DebugStorage = True

    dtx = InvocationTransaction()
    dtx.Version = 1
    dtx.outputs = []
    dtx.inputs = []
    dtx.scripts = []
    dtx.Script = binascii.unhexlify(deploy_script)

    if from_addr is not None:
        from_addr = PromptUtils.lookup_addr_str(wallet, from_addr)

    try:
        dtx = wallet.MakeTransaction(tx=dtx, from_addr=from_addr)
    except (ValueError):
        pass

    context = ContractParametersContext(dtx)
    wallet.Sign(context)
    dtx.scripts = context.GetScripts()

    contract = wallet.GetDefaultContract()
    dtx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=Crypto.ToScriptHash(contract.Script, unhex=False))]
    dtx.Attributes = make_unique_script_attr(dtx.Attributes)

    to_dispatch = []

    if snapshot is None:
        snapshot = GetBlockchain()._db.createSnapshot().Clone()
    engine = ApplicationEngine(
        trigger_type=TriggerType.Application,
        container=dtx,
        snapshot=snapshot,
        gas=dtx.Gas,
        testMode=True
    )

    engine.LoadScript(dtx.Script)

    # first we will execute the test deploy
    # then right after, we execute the test invoke
    if enable_debugger:
        debugger = Debugger(engine)
        d_success = debugger.Execute()
    else:
        d_success = engine.Execute()

    # the old setup provided the same StateMachine object to the ApplicationEngine for deploy and invoke
    # this allowed for a single dispatch of events at the end of the function. Now a new StateMachine is automatically
    # created when creating an ApplicationEngine, thus we have to dispatch events after the deploy to not lose them as
    # testcases expect them
    to_dispatch = to_dispatch + engine._Service.events_to_dispatch
    for event in to_dispatch:
        events.emit(event.event_type, event)
    to_dispatch = []

    if d_success:

        items = engine.ResultStack.Items

        contract_state = None
        for i in items:
            if type(i) is ContractState:
                contract_state = i
                break
            elif type(i) is InteropInterface:
                item = i.GetInterface()
                if type(item) is ContractState:
                    contract_state = item
                    break

        shash = contract_state.Code.ScriptHash()

        invoke_args, neo_to_attach, gas_to_attach = PromptUtils.get_asset_attachments(invoke_args)
        invoke_args, no_parse_addresses = PromptUtils.get_parse_addresses(invoke_args)

        invoke_args.reverse()

        if '--i' in invoke_args:
            invoke_args = []
            for index, iarg in enumerate(contract_state.Code.ParameterList):
                param, abort = PromptUtils.gather_param(index, iarg)
                if abort:
                    return None, [], 0, None
                else:
                    invoke_args.append(param)
            invoke_args.reverse()

        sb = ScriptBuilder()

        for p in invoke_args:
            process_params(sb, p, wallet, no_parse_addresses)

        sb.EmitAppCall(shash.Data)
        out = sb.ToArray()

        outputs = []

        if neo_to_attach:
            output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash,
                                       Value=neo_to_attach,
                                       script_hash=contract_state.Code.ScriptHash(),
                                       )
            outputs.append(output)

        if gas_to_attach:
            output = TransactionOutput(AssetId=Blockchain.SystemCoin().Hash,
                                       Value=gas_to_attach,
                                       script_hash=contract_state.Code.ScriptHash())

            outputs.append(output)

        itx = InvocationTransaction()
        itx.Version = 1
        itx.outputs = outputs
        itx.inputs = []
        itx.scripts = []
        itx.Attributes = deepcopy(invoke_attrs) if invoke_attrs else []
        itx.Script = binascii.unhexlify(out)

        if len(outputs) < 1 and not owners:
            contract = wallet.GetDefaultContract()
            itx.Attributes.append(TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                                       data=contract.ScriptHash))
            itx.Attributes = make_unique_script_attr(itx.Attributes)

        try:
            itx = wallet.MakeTransaction(tx=itx, from_addr=from_addr)
        except (ValueError):
            pass

        context = ContractParametersContext(itx)
        wallet.Sign(context)

        if owners:
            owners = list(owners)
            for owner in owners:
                itx.Attributes.append(TransactionAttribute(usage=TransactionAttributeUsage.Script, data=owner))
                itx.Attributes = make_unique_script_attr(itx.Attributes)
            context = ContractParametersContext(itx, isMultiSig=True)

        if context.Completed:
            itx.scripts = context.GetScripts()
        else:
            logger.warn("Not gathering signatures for test build.  For a non-test invoke that would occur here.")

        engine = ApplicationEngine(
            trigger_type=TriggerType.Application,
            container=itx,
            snapshot=snapshot,
            gas=itx.Gas,
            testMode=invocation_test_mode
        )

        engine.invocation_args = invoke_args
        engine.LoadScript(itx.Script)
        engine.LoadDebugInfoForScriptHash(debug_map, shash.Data)

        if enable_debugger:
            debugger = Debugger(engine)
            i_success = debugger.Execute()
        else:
            i_success = engine.Execute()

        engine._Service.ExecutionCompleted(engine, i_success)
        to_dispatch = to_dispatch + engine._Service.events_to_dispatch

        for event in to_dispatch:
            events.emit(event.event_type, event)

        if i_success:
            if len(engine._Service.notifications) > 0:

                for n in engine._Service.notifications:
                    Blockchain.Default().OnNotify(n)

            logger.info("Used %s Gas " % engine.GasConsumed().ToString())

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed = consumed.Ceil()

            if consumed <= Fixed8.Zero():
                consumed = min_fee

            total_ops = engine.ops_processed

            # set the amount of gas the tx will need
            itx.Gas = consumed
            itx.Attributes = []
            result = engine.ResultStack.Items
            return itx, result, total_ops, engine
        else:
            print("error executing invoke contract...")

    else:
        print("error executing deploy contract.....")

    # service.ExecutionCompleted(engine, False, 'error')

    return None, [], 0, None
Пример #24
0
 def CheckWitnessPubkey(self, engine, pubkey):
     scripthash = Contract.CreateSignatureRedeemScript(pubkey)
     return self.CheckWitnessHash(engine, Crypto.ToScriptHash(scripthash))
Пример #25
0
    def Contract_Create(self, engine: ExecutionEngine):

        script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(script) > 1024 * 1024:
            return False

        param_list = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()
        if len(param_list) > 252:
            return False
        return_type = int(
            engine.CurrentContext.EvaluationStack.Pop().GetBigInteger())
        contract_properties = int(
            engine.CurrentContext.EvaluationStack.Pop().GetBigInteger())

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        name = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        code_version = engine.CurrentContext.EvaluationStack.Pop(
        ).GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        author = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        email = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 65536:
            return False

        description = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        )

        hash = Crypto.ToScriptHash(script, unhex=False)

        contract = self._contracts.TryGet(hash.ToBytes())

        if contract is None:
            code = FunctionCode(script=script,
                                param_list=param_list,
                                return_type=return_type,
                                contract_properties=contract_properties)

            contract = ContractState(code, contract_properties, name,
                                     code_version, author, email, description)

            self._contracts.GetAndChange(code.ScriptHash().ToBytes(), contract)

            self._contracts_created[hash.ToBytes()] = UInt160(
                data=engine.CurrentContext.ScriptHash())

        engine.CurrentContext.EvaluationStack.PushT(
            StackItem.FromInterface(contract))

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.CONTRACT_CREATED,
                               ContractParameter(
                                   ContractParameterType.InteropInterface,
                                   contract),
                               hash,
                               Blockchain.Default().Height + 1,
                               engine.ScriptContainer.Hash
                               if engine.ScriptContainer else None,
                               test_mode=engine.testMode))
        return True
Пример #26
0
    def Contract_Migrate(self, engine: ExecutionEngine):

        script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(script) > 1024 * 1024:
            return False

        param_list = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(param_list) > 252:
            return False

        return_type = int(
            engine.CurrentContext.EvaluationStack.Pop().GetBigInteger())

        contract_properties = engine.CurrentContext.EvaluationStack.Pop(
        ).GetBigInteger()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False

        name = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        version = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        author = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        email = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 65536:
            return False
        description = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        hash = Crypto.ToScriptHash(script, unhex=False)

        contract = self._contracts.TryGet(hash.ToBytes())

        if contract is None:

            code = FunctionCode(script=script,
                                param_list=param_list,
                                return_type=return_type)

            contract = ContractState(code=code,
                                     contract_properties=contract_properties,
                                     name=name,
                                     version=version,
                                     author=author,
                                     email=email,
                                     description=description)

            self._contracts.Add(hash.ToBytes(), contract)

            self._contracts_created[hash.ToBytes()] = UInt160(
                data=engine.CurrentContext.ScriptHash())

            if contract.HasStorage:
                for key, val in self._storages.Find(
                        engine.CurrentContext.ScriptHash()).items():
                    key = StorageKey(script_hash=hash, key=key)
                    item = StorageItem(val)
                    self._storages.Add(key.ToArray(), item)

        engine.CurrentContext.EvaluationStack.PushT(
            StackItem.FromInterface(contract))

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.CONTRACT_MIGRATED,
                               ContractParameter(
                                   ContractParameterType.InteropInterface,
                                   contract),
                               hash,
                               Blockchain.Default().Height + 1,
                               engine.ScriptContainer.Hash
                               if engine.ScriptContainer else None,
                               test_mode=engine.testMode))

        return self.Contract_Destroy(engine)