diff --git a/.travis.yml b/.travis.yml index 99ba39c1b..926cea97e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ install: - pip install coveralls - yes | pip uninstall neo-boa neocore - pip install -e git+https://github.com/CityOfZion/neo-boa@development#egg=neo-boa - - pip install -e git+https://github.com/CityOfZion/neo-python-core@master#egg=neocore + - pip install -e git+https://github.com/CityOfZion/neo-python-core@development#egg=neocore env: - NEOPYTHON_UNITTEST=1 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dcaac22ea..f9151a787 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,6 +11,7 @@ All notable changes to this project are documented in this file. - Support cancelling actions with ``KeyboardInterrupt`` - Enhance output of `wallet` cli command - Fixed size calculation for `RegisterTransaction` +- Support updating np-core to throw exceptions instead of logging errors `#888 `_ [0.8.4] 2019-02-14 diff --git a/neo/Core/BlockBase.py b/neo/Core/BlockBase.py index cfb5921bb..75c26a1b9 100644 --- a/neo/Core/BlockBase.py +++ b/neo/Core/BlockBase.py @@ -119,7 +119,7 @@ def Deserialize(self, reader): """ self.__hash = None self.DeserializeUnsigned(reader) - byt = reader.ReadByte() + byt = ord(reader.ReadByte()) if int(byt) != 1: raise Exception('Incorrect format') diff --git a/neo/Core/FunctionCode.py b/neo/Core/FunctionCode.py index f54b3c13f..7e8038349 100644 --- a/neo/Core/FunctionCode.py +++ b/neo/Core/FunctionCode.py @@ -84,7 +84,7 @@ def Deserialize(self, reader): """ self.Script = reader.ReadVarBytes() self.ParameterList = reader.ReadVarBytes() - self.ReturnType = reader.ReadByte() + self.ReturnType = ord(reader.ReadByte()) def Serialize(self, writer): """ diff --git a/neo/Core/Header.py b/neo/Core/Header.py index 551263702..f1c1e9dc4 100644 --- a/neo/Core/Header.py +++ b/neo/Core/Header.py @@ -36,7 +36,7 @@ def Deserialize(self, reader): reader (neo.IO.BinaryReader): """ super(Header, self).Deserialize(reader) - if reader.ReadByte() != 0: + if ord(reader.ReadByte()) != 0: raise Exception('Incorrect Header Format') def Equals(self, other): diff --git a/neo/Core/State/AssetState.py b/neo/Core/State/AssetState.py index 948feaa8a..96d887bae 100644 --- a/neo/Core/State/AssetState.py +++ b/neo/Core/State/AssetState.py @@ -103,19 +103,19 @@ def Deserialize(self, reader): """ super(AssetState, self).Deserialize(reader) self.AssetId = reader.ReadUInt256() - self.AssetType = reader.ReadByte() + self.AssetType = ord(reader.ReadByte()) self.Name = reader.ReadVarString() position = reader.stream.tell() try: self.Amount = reader.ReadFixed8() - except Exception as e: + except Exception: reader.stream.seek(position) self.Amount = reader.ReadFixed8() self.Available = reader.ReadFixed8() - self.Precision = reader.ReadByte() + self.Precision = ord(reader.ReadByte()) # fee mode reader.ReadByte() diff --git a/neo/Core/State/StateBase.py b/neo/Core/State/StateBase.py index 89d40b2fd..c94423456 100644 --- a/neo/Core/State/StateBase.py +++ b/neo/Core/State/StateBase.py @@ -36,7 +36,7 @@ def Deserialize(self, reader): Raises: Exception: if the state version is incorrect. """ - sv = reader.ReadByte() + sv = ord(reader.ReadByte()) if sv != self.StateVersion: raise Exception("Incorrect State format") diff --git a/neo/Core/State/StateDescriptor.py b/neo/Core/State/StateDescriptor.py index 704026eb5..33ddcd5e9 100644 --- a/neo/Core/State/StateDescriptor.py +++ b/neo/Core/State/StateDescriptor.py @@ -45,7 +45,7 @@ def Deserialize(self, reader: BinaryReader): reader (neocore.IO.BinaryReader): """ - self.Type = StateType(reader.ReadByte()) + self.Type = StateType(ord(reader.ReadByte())) self.Key = reader.ReadVarBytes(max=100) self.Field = reader.ReadVarString(max=32).decode('utf-8') diff --git a/neo/Core/State/UnspentCoinState.py b/neo/Core/State/UnspentCoinState.py index 386e61138..fedb6b218 100644 --- a/neo/Core/State/UnspentCoinState.py +++ b/neo/Core/State/UnspentCoinState.py @@ -84,7 +84,7 @@ def Deserialize(self, reader): blen = reader.ReadVarInt() self.Items = [0] * blen for i in range(0, blen): - self.Items[i] = int.from_bytes(reader.ReadByte(do_ord=False), 'little') + self.Items[i] = int.from_bytes(reader.ReadByte(), 'little') @staticmethod def DeserializeFromDB(buffer): diff --git a/neo/Core/TX/RegisterTransaction.py b/neo/Core/TX/RegisterTransaction.py index d4b08917f..dabe85f03 100644 --- a/neo/Core/TX/RegisterTransaction.py +++ b/neo/Core/TX/RegisterTransaction.py @@ -103,10 +103,10 @@ def DeserializeExclusiveData(self, reader): reader (neo.IO.BinaryReader): """ self.Type = TransactionType.RegisterTransaction - self.AssetType = reader.ReadByte() + self.AssetType = ord(reader.ReadByte()) self.Name = reader.ReadVarString() self.Amount = reader.ReadFixed8() - self.Precision = reader.ReadByte() + self.Precision = ord(reader.ReadByte()) self.Owner = ECDSA.Deserialize_Secp256r1(reader) # self.Owner = ecdsa.G self.Admin = reader.ReadUInt160() diff --git a/neo/Core/TX/Transaction.py b/neo/Core/TX/Transaction.py index 6a70b0ac5..a4eea2dc0 100644 --- a/neo/Core/TX/Transaction.py +++ b/neo/Core/TX/Transaction.py @@ -441,7 +441,7 @@ def DeserializeFrom(reader): Returns: Transaction: """ - ttype = reader.ReadByte() + ttype = ord(reader.ReadByte()) tx = None from neo.Core.TX.RegisterTransaction import RegisterTransaction @@ -499,7 +499,7 @@ def DeserializeUnsigned(self, reader): Raises: Exception: if transaction type is incorrect. """ - txtype = reader.ReadByte() + txtype = ord(reader.ReadByte()) if txtype != int.from_bytes(self.Type, 'little'): raise Exception('incorrect type {}, wanted {}'.format(txtype, int.from_bytes(self.Type, 'little'))) self.DeserializeUnsignedWithoutType(reader) @@ -511,7 +511,7 @@ def DeserializeUnsignedWithoutType(self, reader): Args: reader (neo.IO.BinaryReader): """ - self.Version = reader.ReadByte() + self.Version = ord(reader.ReadByte()) self.DeserializeExclusiveData(reader) self.Attributes = reader.ReadSerializableArray('neo.Core.TX.TransactionAttribute.TransactionAttribute', max=self.MAX_TX_ATTRIBUTES) diff --git a/neo/Core/TX/TransactionAttribute.py b/neo/Core/TX/TransactionAttribute.py index f536f0d6c..85a38df08 100644 --- a/neo/Core/TX/TransactionAttribute.py +++ b/neo/Core/TX/TransactionAttribute.py @@ -84,7 +84,7 @@ def Deserialize(self, reader): Args: reader (neo.IO.BinaryReader): """ - usage = reader.ReadByte() + usage = ord(reader.ReadByte()) self.Usage = usage if usage == TransactionAttributeUsage.ContractHash or usage == TransactionAttributeUsage.Vote or \ @@ -99,7 +99,7 @@ def Deserialize(self, reader): elif usage == TransactionAttributeUsage.DescriptionUrl: - self.Data = reader.ReadBytes(reader.ReadByte()) + self.Data = reader.ReadBytes(ord(reader.ReadByte())) elif usage == TransactionAttributeUsage.Description or usage >= TransactionAttributeUsage.Remark: self.Data = reader.ReadVarBytes(max=self.MAX_ATTR_DATA_SIZE) diff --git a/neo/Network/Payloads/InvPayload.py b/neo/Network/Payloads/InvPayload.py index b82bccd48..aa29128ab 100644 --- a/neo/Network/Payloads/InvPayload.py +++ b/neo/Network/Payloads/InvPayload.py @@ -42,7 +42,7 @@ def Deserialize(self, reader): Args: reader (neo.IO.BinaryReader): """ - self.Type = reader.ReadByte() + self.Type = ord(reader.ReadByte()) self.Hashes = reader.ReadHashes() def Serialize(self, writer): diff --git a/neo/Prompt/Commands/Invoke.py b/neo/Prompt/Commands/Invoke.py index be73b4c2f..ff63117cb 100644 --- a/neo/Prompt/Commands/Invoke.py +++ b/neo/Prompt/Commands/Invoke.py @@ -660,6 +660,10 @@ def gather_signatures(context, itx, owners): else: print("Public Key does not match address %s " % next_addr) + except ValueError: + # expected from ECDSA if public key is invalid + print(f"Invalid public key: {items[0]}") + do_exit = True except EOFError: # Control-D pressed: quit do_exit = True diff --git a/neo/Prompt/Utils.py b/neo/Prompt/Utils.py index e9698832a..7a2a98bfb 100644 --- a/neo/Prompt/Utils.py +++ b/neo/Prompt/Utils.py @@ -329,7 +329,10 @@ def gather_param(index, param_type, do_continue=True): elif ptype == ContractParameterType.Boolean: return bool(result), False elif ptype == ContractParameterType.PublicKey: - return ECDSA.decode_secp256r1(result).G, False + try: + return ECDSA.decode_secp256r1(result).G, False + except ValueError: + return None, True elif ptype == ContractParameterType.ByteArray: if isinstance(result, str) and len(result) == 34 and result[0] == 'A': return Helper.AddrStrToScriptHash(result).Data, False diff --git a/neo/Prompt/test_utils.py b/neo/Prompt/test_utils.py index 476f8e00f..60f55ad80 100644 --- a/neo/Prompt/test_utils.py +++ b/neo/Prompt/test_utils.py @@ -270,6 +270,13 @@ def test_gather_param(self): 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: diff --git a/neo/SmartContract/ContractParameterContext.py b/neo/SmartContract/ContractParameterContext.py index 039e491de..2abf4905c 100755 --- a/neo/SmartContract/ContractParameterContext.py +++ b/neo/SmartContract/ContractParameterContext.py @@ -165,10 +165,14 @@ def AddSignature(self, contract, pubkey, signature): ms = MemoryStream(binascii.unhexlify(contract.Script)) reader = BinaryReader(ms) numr = reader.ReadUInt8() - while reader.ReadUInt8() == 33: - ecpoint = ecdsa.ec.decode_from_hex(binascii.hexlify(reader.ReadBytes(33)).decode()) - points.append(ecpoint) - ms.close() + try: + while reader.ReadUInt8() == 33: + ecpoint = ecdsa.ec.decode_from_hex(binascii.hexlify(reader.ReadBytes(33)).decode()) + points.append(ecpoint) + except ValueError: + return False + finally: + ms.close() if pubkey not in points: return False diff --git a/neo/SmartContract/StateMachine.py b/neo/SmartContract/StateMachine.py index fb1f88207..571919eec 100644 --- a/neo/SmartContract/StateMachine.py +++ b/neo/SmartContract/StateMachine.py @@ -146,7 +146,10 @@ def Asset_Create(self, engine: ExecutionEngine): ownerData = engine.CurrentContext.EvaluationStack.Pop().GetByteArray() - owner = ECDSA.decode_secp256r1(ownerData, unhex=False).G + try: + owner = ECDSA.decode_secp256r1(ownerData, unhex=False).G + except ValueError: + return False if owner.IsInfinity: return False diff --git a/neo/SmartContract/StateReader.py b/neo/SmartContract/StateReader.py index be31368be..a5cdd0448 100644 --- a/neo/SmartContract/StateReader.py +++ b/neo/SmartContract/StateReader.py @@ -346,7 +346,10 @@ def Runtime_CheckWitness(self, engine: ExecutionEngine): result = self.CheckWitnessHash(engine, UInt160(data=hashOrPubkey)) elif len(hashOrPubkey) == 33: - point = ECDSA.decode_secp256r1(hashOrPubkey, unhex=False).G + try: + point = ECDSA.decode_secp256r1(hashOrPubkey, unhex=False).G + except ValueError: + return False result = self.CheckWitnessPubkey(engine, point) else: return False diff --git a/neo/VM/ExecutionEngine.py b/neo/VM/ExecutionEngine.py index 110137144..318d315b7 100644 --- a/neo/VM/ExecutionEngine.py +++ b/neo/VM/ExecutionEngine.py @@ -160,7 +160,7 @@ def ExecuteOp(self, opcode, context: ExecutionContext): estack.PushT(bytearray(0)) elif opcode == PUSHDATA1: - lenngth = context.OpReader.ReadByte() + lenngth = ord(context.OpReader.ReadByte()) estack.PushT(bytearray(context.OpReader.SafeReadBytes(lenngth))) elif opcode == PUSHDATA2: estack.PushT(context.OpReader.SafeReadBytes(context.OpReader.ReadUInt16())) @@ -887,8 +887,8 @@ def ExecuteOp(self, opcode, context: ExecutionContext): # stack isolation elif opcode == CALL_I: - rvcount = context.OpReader.ReadByte() - pcount = context.OpReader.ReadByte() + rvcount = ord(context.OpReader.ReadByte()) + pcount = ord(context.OpReader.ReadByte()) if estack.Count < pcount: return self.VM_FAULT_and_report(VMFault.UNKNOWN_STACKISOLATION) @@ -906,8 +906,8 @@ def ExecuteOp(self, opcode, context: ExecutionContext): if self._Table is None: return self.VM_FAULT_and_report(VMFault.UNKNOWN_STACKISOLATION2) - rvcount = context.OpReader.ReadByte() - pcount = context.OpReader.ReadByte() + rvcount = ord(context.OpReader.ReadByte()) + pcount = ord(context.OpReader.ReadByte()) if estack.Count < pcount: return self.VM_FAULT_and_report(VMFault.UNKNOWN_STACKISOLATION) @@ -998,7 +998,7 @@ def StepInto(self): if self.CurrentContext.InstructionPointer >= len(self.CurrentContext.Script): op = RET else: - op = self.CurrentContext.OpReader.ReadByte(do_ord=False) + op = self.CurrentContext.OpReader.ReadByte() self.ops_processed += 1 diff --git a/neo/VM/InteropService.py b/neo/VM/InteropService.py index 051012b31..8cdde5b0a 100644 --- a/neo/VM/InteropService.py +++ b/neo/VM/InteropService.py @@ -81,7 +81,7 @@ def DeserializeStackItem(reader): if stype == StackItemType.ByteArray: return ByteArray(reader.ReadVarBytes()) elif stype == StackItemType.Boolean: - return Boolean(reader.ReadByte()) + return Boolean(ord(reader.ReadByte())) elif stype == StackItemType.Integer: return Integer(BigInteger.FromBytes(reader.ReadVarBytes(), signed=True)) elif stype == StackItemType.Array: