def test_dunder_methods(self): u1 = UInt160(b'12345678901234567890') u1b = UIntBase(20, b'12345678901234567890') u_larger = UInt160(b'12345678901234567891') u_smaller = UInt160(b'12345678901234567880') self.assertTrue(u1 < u_larger) self.assertTrue(u1 <= u_larger) self.assertTrue(u1 <= u1b) self.assertTrue(u1 == u1b) self.assertTrue(u1b == u1) self.assertTrue(u1 >= u1b) self.assertTrue(u1 >= u_smaller) self.assertTrue(u1 > u_smaller)
def CheckDynamicInvoke(self): if self.CurrentContext.InstructionPointer >= len( self.CurrentContext.Script): return True opcode = self.CurrentContext.NextInstruction if opcode == APPCALL: # read the current position of the stream start_pos = self.CurrentContext.OpReader.stream.tell() # normal app calls are stored in the op reader # we read ahead past the next instruction 1 the next 20 bytes script_hash = self.CurrentContext.OpReader.ReadBytes(21)[1:] # then reset the position self.CurrentContext.OpReader.stream.seek(start_pos) for b in script_hash: # if any of the bytes are greater than 0, this is a normal app call if b > 0: return True # if this is a dynamic app call, we will arrive here # get the current executing script hash current = UInt160(data=self.CurrentContext.ScriptHash()) current_contract_state = self._Table.GetContractState( current.ToBytes()) # if current contract state cant do dynamic calls, return False return current_contract_state.HasDynamicInvoke return True
def __init__(self, asset_id=None, asset_type=None, name=None, amount=Fixed8(0), available=Fixed8(0), precision=0, fee_mode=0, fee=Fixed8(0), fee_addr=UInt160(data=bytearray(20)), owner=None, admin=None, issuer=None, expiration=None, is_frozen=False): self.AssetId = asset_id self.AssetType = asset_type self.Name = name self.Amount = amount self.Available = available self.Precision = precision self.FeeMode = fee_mode self.Fee = fee self.FeeAddress = fee_addr if owner is not None and type(owner) is not EllipticCurve.ECPoint: raise Exception("Owner must be ECPoint Instance") self.Owner = owner self.Admin = admin self.Issuer = issuer self.Expiration = expiration self.IsFrozen = is_frozen
def ToJson(self, verbose=False): assets = self.GetCoinAssets() if Blockchain.Default().Height == 0: percent_synced = 0 else: percent_synced = int(100 * self._current_height / Blockchain.Default().Height) jsn = {} jsn['path'] = self._path addresses = [ Crypto.ToAddress(UInt160(data=addr.ScriptHash)) for addr in Address.select() ] jsn['addresses'] = addresses jsn['height'] = self._current_height jsn['percent_synced'] = percent_synced jsn['balances'] = [ "%s : %s " % (asset.ToString(), self.GetBalance(asset).value / Fixed8.D) for asset in assets ] jsn['public_keys'] = self.PubKeys() if verbose: jsn['coins'] = [coin.ToJson() for coin in self.FindUnspentCoins()] jsn['transactions'] = [ tx.ToJson() for tx in self.GetTransactions() ] return jsn
def Contract_Create(self, engine): script = engine.EvaluationStack.Pop().GetByteArray() if len(script) > 1024 * 1024: return False param_list = engine.EvaluationStack.Pop().GetByteArray() if len(param_list) > 252: return False return_type = int(engine.EvaluationStack.Pop().GetBigInteger()) needs_storage = engine.EvaluationStack.Pop().GetBoolean() if len(engine.EvaluationStack.Peek().GetByteArray()) > 252: return False name = engine.EvaluationStack.Pop().GetByteArray() if len(engine.EvaluationStack.Peek().GetByteArray()) > 252: return False code_version = engine.EvaluationStack.Pop().GetByteArray() if len(engine.EvaluationStack.Peek().GetByteArray()) > 252: return False author = engine.EvaluationStack.Pop().GetByteArray() if len(engine.EvaluationStack.Peek().GetByteArray()) > 252: return False email = engine.EvaluationStack.Pop().GetByteArray() if len(engine.EvaluationStack.Peek().GetByteArray()) > 65536: return False description = engine.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 = ContractState(code, needs_storage, name, code_version, author, email, description) self._contracts.GetAndChange(code.ScriptHash().ToBytes(), contract) self._contracts_created[hash.ToBytes()] = UInt160( data=engine.CurrentContext.ScriptHash()) engine.EvaluationStack.PushT(StackItem.FromInterface(contract)) # print("*****************************************************") # print("CREATED CONTRACT %s " % hash.ToBytes()) # print("*****************************************************") return True
def Storage_Delete(self, engine): context = engine.EvaluationStack.Pop().GetInterface() if not self.CheckStorageContext(context): return False key = engine.EvaluationStack.Pop().GetByteArray() storage_key = StorageKey(script_hash=context.ScriptHash, key=key) keystr = key if len(key) == 20: keystr = Crypto.ToAddress(UInt160(data=key)) dispatch_smart_contract_event(SmartContractEvent.STORAGE_DELETE, keystr, context.ScriptHash, Blockchain.Default().Height, engine.ScriptContainer.Hash, test_mode=engine.testMode) self._storages.Remove(storage_key.GetHashCodeBytes()) return True
def Addresses(self): result = [] for addr in Address.select(): addr_str = Crypto.ToAddress(UInt160(data=addr.ScriptHash)) result.append(addr_str) return result
def Runtime_Log(self, engine): message = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8') log = LogEventArgs(engine.ScriptContainer, UInt160(data=engine.CurrentContext.ScriptHash), message) self.LogEvent.on_change(log) return True
def Storage_GetContext(self, engine): hash = UInt160( data= engine.CurrentContext.ScriptHash()) context = StorageContext(script_hash=hash) engine.EvaluationStack.PushT(StackItem.FromInterface(context)) return True
def ExecutionCompleted(self, engine, success, error=None): # commit storages right away if success: self.Commit() height = Blockchain.Default().Height tx_hash = engine.ScriptContainer.Hash entry_script = None try: # get the first script that was executed # this is usually the script that sets up the script to be executed entry_script = UInt160(data=engine.ExecutedScriptHashes[0]) # ExecutedScriptHashes[1] will usually be the first contract executed if len(engine.ExecutedScriptHashes) > 1: entry_script = UInt160(data=engine.ExecutedScriptHashes[1]) except Exception as e: print("Could not get entry script: %s " % e) payload = [] for item in engine.EvaluationStack.Items: payload_item = stack_item_to_py(item) payload.append(payload_item) if success: # dispatch all notify events, along with the success of the contract execution for notify_event_args in self.notifications: dispatch_smart_contract_event( SmartContractEvent.RUNTIME_NOTIFY, notify_event_args.State, notify_event_args.ScriptHash, height, tx_hash, success, engine.testMode) dispatch_smart_contract_event(SmartContractEvent.EXECUTION_SUCCESS, payload, entry_script, height, tx_hash, success, engine.testMode) else: dispatch_smart_contract_event(SmartContractEvent.EXECUTION_FAIL, [payload, error, engine._VMState], entry_script, height, tx_hash, success, engine.testMode)
def Blockchain_GetAccount(self, engine): hash = UInt160(data=engine.EvaluationStack.Pop().GetByteArray()) address = Crypto.ToAddress(hash).encode('utf-8') account = self._accounts.TryGet(address) if account: engine.EvaluationStack.PushT(StackItem.FromInterface(account)) return True return False
def Blockchain_GetContract(self, engine): hash = UInt160(data = engine.EvaluationStack.Pop().GetByteArray()) contract = None if Blockchain.Default() is not None: contract = Blockchain.Default().GetContract(hash) engine.EvaluationStack.PushT(StackItem.FromInterface(contract)) return True
def Runtime_Notify(self, engine): state = engine.EvaluationStack.Pop() notice = NotifyEventArgs( engine.ScriptContainer, UInt160(data=engine.CurrentContext.ScriptHash), state) self.NotifyEvent.on_change(notice) return True
def RawBytesToScriptHash(raw): rawh = binascii.unhexlify(raw) rawhashstr = binascii.unhexlify(bytes(Crypto.Hash160(rawh), encoding='utf-8')) # h160bytes = bytearray(rawhashstr) # h160bytes.reverse() # out = bytes(h160bytes.hex(), encoding='utf-8') # return out return UInt160(data=rawhashstr)
def notify_refund(event_args): to = event_args[0].GetByteArray() if len(to) == 20: to = Crypto.ToAddress(UInt160(data=to)) print("[Neo.Runtime.Notify :: REFUND] TO %s " % to) amount = event_args[1].GetBigInteger() print("[Neo.Runtime.Notify :: REFUND] amount %s " % amount)
def notify_transfer(event_args): tfrom = event_args[0].GetByteArray() tto = event_args[1].GetByteArray() tamount = event_args[2].GetBigInteger() fromaddr = tfrom toaddr = tto try: if len(fromaddr) == 20: fromaddr = Crypto.ToAddress(UInt160(data=tfrom)) if len(toaddr) == 20: toaddr = Crypto.ToAddress(UInt160(data=tto)) except Exception as e: print("Couldnt convert from/to to address %s " % e) print("[Neo.Runtime.Notify :: Transfer] %s from %s to %s " % (tamount, fromaddr, toaddr))
def Blockchain_GetContract(self, engine): hash = UInt160(data=engine.EvaluationStack.Pop().GetByteArray()) contract = self._contracts.TryGet(hash.ToBytes()) if contract: engine.EvaluationStack.PushT(StackItem.FromInterface(contract)) return True return False
def notify_other(event_name, event_args): to = event_args[0].GetByteArray() if len(to) == 20: to = Crypto.ToAddress(UInt160(data=to)) ename = event_name.upper() print("[Neo.Runtime.Notify :: %s] TO %s " % (ename, to)) amount = event_args[1].GetBigInteger() print("[Neo.Runtime.Notify :: %s] amount %s " % (ename, amount))
def FromDBInstance(db_token): hash_ar = bytearray(binascii.unhexlify(db_token.ContractHash)) hash_ar.reverse() hash = UInt160(data=hash_ar) token = NEP5Token(script=None) token.SetScriptHash(hash) token.name = db_token.Name token.symbol = db_token.Symbol token.decimals = db_token.Decimals return token
def test_to_address_alt_version(self): original_version = settings.ADDRESS_VERSION settings.ADDRESS_VERSION = 42 script_hash = UInt160( data=b'B\x11#x\xff\xa3,Le\xd5\x13\xaa5\x06\x89\xdf\xf68\x11T') self.assertEqual(Crypto.ToAddress(script_hash), 'J1DfV2jS511SMtP6dH5ckr3Nwf26kbFx7s') settings.ADDRESS_VERSION = original_version
def Blockchain_GetAccount(self, engine): data = engine.EvaluationStack.Pop().GetByteArray() account = None if Blockchain.Default() is not None: account = Blockchain.Default().GetAccountState(UInt160(data=data)) engine.EvaluationStack.PushT(StackItem.FromInterface(account)) return True
def ToScriptHash(self, address): data = b58decode(address) if len(data) != 25: raise ValueError('Not correct Address, wrong length.') if data[0] != self.AddressVersion: raise ValueError('Not correct Coin Version') checksum = Crypto.Default().Hash256(data[:21])[:4] if checksum != data[21:]: raise Exception('Address format error') return UInt160(data=data[1:21])
def test_5_addr_conv(self): wallet = self.GetWallet1() addr = UInt160( data=b'\xec\xa8\xfc\xf9Nz*\x7f\xc3\xfdT\xae\x0e\xd3\xd3MR\xec%\x90' ) addr_str = 'AdMDZGto3xWozB1HSjjVv27RL3zUM8LzpV' to_uint = wallet.ToScriptHash(addr_str) self.assertEqual(to_uint, addr)
def test_4_delete_addr(self): wallet = self.GetWallet1() self.assertEqual(len(wallet.GetContracts()), 2) imported_addr = UInt160( data=b'\xec\xa8\xfc\xf9Nz*\x7f\xc3\xfdT\xae\x0e\xd3\xd3MR\xec%\x90' ) wallet.DeleteAddress(imported_addr) self.assertEqual(len(wallet.GetContracts()), 1)
def test_compareto_valid(self): u1 = UInt160(b'12345678901234567890') # Same value should return 0 u2 = UIntBase(20, b'12345678901234567890') self.assertEqual(u1.CompareTo(u2), 0) # Higher digit in 'other' should return -1 u2 = UIntBase(20, b'12345678901234567891') self.assertEqual(u1.CompareTo(u2), -1) # Lower digit in 'other' should return 1 u2 = UIntBase(20, b'12345678901234567980') self.assertEqual(u1.CompareTo(u2), 1) # CompareTo across different UIntBase subclasses data = b'12345678901234567890' self.assertEqual(UInt160(data).CompareTo(UIntBase(len(data), data)), 0) self.assertEqual(UIntBase(len(data), data).CompareTo(UInt160(data)), 0) data = b'12345678901234567890123456789012' self.assertEqual(UInt256(data).CompareTo(UIntBase(len(data), data)), 0) self.assertEqual(UIntBase(len(data), data).CompareTo(UInt256(data)), 0)
def Runtime_Log(self, engine): message = engine.EvaluationStack.Pop().GetByteArray() hash = UInt160(data=engine.CurrentContext.ScriptHash()) # Build and emit smart contract event dispatch_smart_contract_event(SmartContractEvent.RUNTIME_LOG, message, hash, Blockchain.Default().Height, engine.ScriptContainer.Hash, test_mode=engine.testMode) return True
def LoadWatchOnly(self): items = [] try: for addr in Address.select(): if addr.IsWatchOnly: watchOnly = UInt160(data=addr.ScriptHash) items.append(watchOnly) return items except Exception as e: logger.error("couldnt load watch only: %s. You may need to migrate your wallet. Run 'wallet migrate'." % e) return []
def Contract_GetStorageContext(self, engine): contract = engine.EvaluationStack.Pop().GetInterface() logger.info("CONTRACT Get storage context %s " % contract) if contract.ScriptHash.ToBytes() in self._contracts_created: created = self._contracts_created[contract.ScriptHash.ToBytes()] if created == UInt160(data=engine.CurrentContext.ScriptHash()): context = StorageContext(script_hash=contract.ScriptHash) engine.EvaluationStack.PushT(StackItem.FromInterface(context)) return True return False
def Storage_Get(self, engine): context = None try: item = engine.EvaluationStack.Pop() context = item.GetInterface('neo.SmartContract.StorageContext.StorageContext') shash = context.ScriptHash except Exception as e: print("could not get storage context %s " % e) return False contract = Blockchain.Default().GetContract(context.ScriptHash.ToBytes()) if contract is not None: if not contract.HasStorage: return False else: return False key = engine.EvaluationStack.Pop().GetByteArray() storage_key = StorageKey(script_hash=context.ScriptHash, key=key) item = Blockchain.Default().GetStorageItem(storage_key) keystr = key valStr = bytearray(0) if item is not None: valStr = bytearray(item.Value) if len(key) == 20: keystr = Crypto.ToAddress(UInt160(data=key)) try: valStr = int.from_bytes(valStr, 'little') except Exception as e: print("couldnt convert %s to number: %s " % (valStr, e)) if item is not None: print("[Neo.Storage.Get] [Script:%s] [%s] -> %s " % (context.ScriptHash, keystr, valStr)) engine.EvaluationStack.PushT(bytearray(item.Value)) else: print("[Neo.Storage.Get] [Script:%s] [%s] -> 0 " % (context.ScriptHash, keystr)) engine.EvaluationStack.PushT(bytearray(0)) return True
def Storage_Get(self, engine): context = None try: item = engine.EvaluationStack.Pop() context = item.GetInterface() shash = context.ScriptHash except Exception as e: logger.error("could not get storage context %s " % e) return False if not self.CheckStorageContext(context): return False key = engine.EvaluationStack.Pop().GetByteArray() storage_key = StorageKey(script_hash=context.ScriptHash, key=key) item = self._storages.TryGet(storage_key.GetHashCodeBytes()) keystr = key valStr = bytearray(0) if item is not None: valStr = bytearray(item.Value) if len(key) == 20: keystr = Crypto.ToAddress(UInt160(data=key)) try: valStr = int.from_bytes(valStr, 'little') except Exception as e: pass if item is not None: engine.EvaluationStack.PushT(bytearray(item.Value)) else: engine.EvaluationStack.PushT(bytearray([0])) dispatch_smart_contract_event(SmartContractEvent.STORAGE_GET, '%s -> %s' % (keystr, valStr), context.ScriptHash, Blockchain.Default().Height, engine.ScriptContainer.Hash, test_mode=engine.testMode) return True