From 30e62008f5caca78b82005b7c2ac5533988b813b Mon Sep 17 00:00:00 2001 From: localhuman Date: Thu, 28 Sep 2017 07:23:57 -0500 Subject: [PATCH] Collection of fixes for smart contract execution errors --- neo/BigInteger.py | 8 +++-- .../Blockchains/LevelDB/LevelDBBlockchain.py | 6 +--- neo/SmartContract/StateReader.py | 4 +-- neo/VM/ExecutionEngine.py | 31 +++++++++++++------ neo/VM/InteropService.py | 3 +- 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/neo/BigInteger.py b/neo/BigInteger.py index e7b2d6409..25b685f84 100644 --- a/neo/BigInteger.py +++ b/neo/BigInteger.py @@ -13,8 +13,12 @@ def Equals(self, other): return super(BigInteger, self).__eq__(other) def ToByteArray(self, signed=True): - return self.to_bytes((self.bit_length() + 7) //8, byteorder='little', signed=signed) - + try: + return self.to_bytes((self.bit_length() + 7) //8, byteorder='little', signed=signed) + except OverflowError: + return self.to_bytes((self.bit_length() + 7) //8, byteorder='little', signed=False) + except Exception: + print("COULD NOT CONVERT %s to byte array" % self) def __abs__(self, *args, **kwargs): # real signature unknown return BigInteger(super(BigInteger, self).__abs__(*args, **kwargs)) diff --git a/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py b/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py index f6260a240..3fd20dcc2 100644 --- a/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py +++ b/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py @@ -655,11 +655,7 @@ def Persist(self, block): except Exception as e: - print("COULD NOT EXECUTE %s " % e) -# self.__log.debug("could not execute %s " % e) -# traceback.print_stack() -# traceback.print_exc() - print("EXECUTION FAILLLLLLLLLLLLLLEDDDDDD") + print("[neo.Implementations.Blockchains.LevelDBBlockchain.PersistBlock: engine execute result] Could not execute smart contract. See logs for more details. %s " % e) else: if tx.Type != b'\x00' and tx.Type != 128: diff --git a/neo/SmartContract/StateReader.py b/neo/SmartContract/StateReader.py index 875e31dd2..f8821baf0 100644 --- a/neo/SmartContract/StateReader.py +++ b/neo/SmartContract/StateReader.py @@ -181,7 +181,7 @@ def CheckWitnessHash(self, engine, hash): def CheckWitnessPubkey(self, engine, pubkey): scripthash = Contract.CreateSignatureRedeemScript(pubkey) - return self.CheckWitnessHash(engine, Crypto.ToScriptHash( Contract.CreateSignatureRedeemScript(pubkey))) + return self.CheckWitnessHash(engine, Crypto.ToScriptHash( scripthash)) def Runtime_CheckWitness(self, engine): @@ -194,7 +194,7 @@ def Runtime_CheckWitness(self, engine): result = False if len(hashOrPubkey) == 20: - result = self.CheckWitnessHash(engine, hashOrPubkey) + result = self.CheckWitnessHash(engine, UInt160(data=hashOrPubkey)) elif len(hashOrPubkey) == 33: point = ECDSA.decode_secp256r1(hashOrPubkey, unhex=False).G diff --git a/neo/VM/ExecutionEngine.py b/neo/VM/ExecutionEngine.py index 486017616..59fd4b681 100644 --- a/neo/VM/ExecutionEngine.py +++ b/neo/VM/ExecutionEngine.py @@ -7,7 +7,7 @@ from neo.SmartContract.ContractParameterType import ContractParameterType from neo.BigInteger import BigInteger import hashlib -from neo.VM.InteropService import Array,Struct +from neo.VM.InteropService import Array,Struct,StackItem import sys,os from neo.UInt160 import UInt160 import traceback @@ -496,10 +496,22 @@ def ExecuteOp(self, opcode, context): elif opcode == NUMEQUAL: - x2 = estack.Pop().GetBigInteger() - x1 = estack.Pop().GetBigInteger() + x2 = estack.Pop() + x1 = estack.Pop() + + try: + x2_val = x2.GetBigInteger() + x1_val = x1.GetBigInteger() + + result = x1_val == x2_val + + estack.PushT( result ) + + except Exception as e: + print("Colud not compare %s and %s : types- %s %s" % (x2,x1, type(x2), type(x1))) + + estack.PushT(False) - estack.PushT( x1 == x2 ) elif opcode == NUMNOTEQUAL: @@ -707,14 +719,14 @@ def ExecuteOp(self, opcode, context): newItem = estack.Pop() - if newItem.IsStruct: + if issubclass(type(newItem), StackItem) and newItem.IsStruct: newItem = newItem.Clone() index = estack.Pop().GetBigInteger() arrItem = estack.Pop() - if not arrItem.IsArray: + if not issubclass(type(arrItem), StackItem) or not arrItem.IsArray: self._VMState |= VMState.FAULT return @@ -752,6 +764,8 @@ def ExecuteOp(self, opcode, context): + + def LoadScript(self, script, push_only=False): context = ExecutionContext(self, script, push_only) @@ -785,9 +799,8 @@ def StepInto(self): try: self.ExecuteOp(op, self.CurrentContext) except Exception as e: - print("could not execute op %s " % e) - traceback.print_stack() - traceback.print_exc() + self.__log.debug("could not execute op %s " % e) + self.__log.error("Exception", exc_info=1) raise e def StepOut(self): diff --git a/neo/VM/InteropService.py b/neo/VM/InteropService.py index 3ab6cd16f..f09a9909f 100644 --- a/neo/VM/InteropService.py +++ b/neo/VM/InteropService.py @@ -154,7 +154,7 @@ def Equals(self, other): def GetBigInteger(self): try: - b = BigInteger.FromBytes(self._value, signed=True) + b = BigInteger(int.from_bytes(self._value, 'little', signed=True)) return b except Exception as e: pass @@ -243,6 +243,7 @@ def __str__(self): class Struct(Array): + @property def IsStruct(self): return True