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) if len(key) == 20: keystr = Crypto.ToAddress(UInt160(data=key)) self.events_to_dispatch.append( SmartContractEvent(SmartContractEvent.STORAGE_DELETE, [keystr], context.ScriptHash, Blockchain.Default().Height + 1, engine.ScriptContainer.Hash if engine.ScriptContainer else None, test_mode=engine.testMode)) self._storages.Remove(storage_key.ToArray()) return True
def Contract_Destroy(self, engine): hash = UInt160(data=engine.CurrentContext.ScriptHash()) contract = self._contracts.TryGet(hash.ToBytes()) if contract is not None: self._contracts.Remove(hash.ToBytes()) if contract.HasStorage: for pair in self._storages.Find(hash.ToBytes()): self._storages.Remove(pair.Key) self.events_to_dispatch.append( SmartContractEvent(SmartContractEvent.CONTRACT_DESTROY, ContractParameter( ContractParameterType.InteropInterface, contract), hash, Blockchain.Default().Height + 1, engine.ScriptContainer.Hash if engine.ScriptContainer else None, test_mode=engine.testMode)) return True
def Storage_Get(self, engine): context = None try: item = engine.EvaluationStack.Pop() context = item.GetInterface() 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.ToArray()) 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)) self.events_to_dispatch.append( SmartContractEvent(SmartContractEvent.STORAGE_GET, ['%s -> %s' % (keystr, valStr)], context.ScriptHash, Blockchain.Default().Height + 1, engine.ScriptContainer.Hash if engine.ScriptContainer else None, test_mode=engine.testMode)) return True
def Storage_Put(self, engine: ExecutionEngine): context = None try: context = engine.CurrentContext.EvaluationStack.Pop().GetInterface( ) except Exception as e: logger.error("Storage Context Not found on stack") return False if not self.CheckStorageContext(context): return False key = engine.CurrentContext.EvaluationStack.Pop().GetByteArray() if len(key) > 1024: return False value = engine.CurrentContext.EvaluationStack.Pop().GetByteArray() new_item = StorageItem(value=value) storage_key = StorageKey(script_hash=context.ScriptHash, key=key) item = self._storages.ReplaceOrAdd(storage_key.ToArray(), new_item) keystr = key 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 self.events_to_dispatch.append( SmartContractEvent( SmartContractEvent.STORAGE_PUT, ContractParameter(ContractParameterType.String, '%s -> %s' % (keystr, valStr)), context.ScriptHash, Blockchain.Default().Height + 1, engine.ScriptContainer.Hash if engine.ScriptContainer else None, test_mode=engine.testMode)) return True
def Contract_Migrate(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()) contract_properties = engine.EvaluationStack.Pop().GetBigInteger() if len(engine.EvaluationStack.Peek().GetByteArray()) > 252: return False name = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8') if len(engine.EvaluationStack.Peek().GetByteArray()) > 252: return False version = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8') if len(engine.EvaluationStack.Peek().GetByteArray()) > 252: return False author = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8') if len(engine.EvaluationStack.Peek().GetByteArray()) > 252: return False email = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8') if len(engine.EvaluationStack.Peek().GetByteArray()) > 65536: return False description = engine.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 pair in self._storages.Find( engine.CurrentContext.ScriptHash()): key = StorageKey(script_hash=hash, key=pair.Key.Key) item = StorageItem(pair.Value.Value) self._storages.Add(key, item) engine.EvaluationStack.PushT(StackItem.FromInterface(contract)) self.events_to_dispatch.append( SmartContractEvent(SmartContractEvent.CONTRACT_MIGRATED, [contract], hash, Blockchain.Default().Height + 1, engine.ScriptContainer.Hash if engine.ScriptContainer else None, test_mode=engine.testMode)) return self.Contract_Destroy(engine)
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()) contract_properties = int(engine.EvaluationStack.Pop().GetBigInteger()) 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_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.EvaluationStack.PushT(StackItem.FromInterface(contract)) self.events_to_dispatch.append( SmartContractEvent(SmartContractEvent.CONTRACT_CREATED, [contract], hash, Blockchain.Default().Height + 1, engine.ScriptContainer.Hash if engine.ScriptContainer else None, test_mode=engine.testMode)) return True
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.Snapshot.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.Snapshot.Contracts.Add(hash.ToBytes(), contract) cur_hash = UInt160(data=engine.CurrentContext.ScriptHash()) self._contracts_created[hash.ToBytes()] = cur_hash if contract.HasStorage: to_add = [] for key, item in self.Snapshot.Storages.Find( cur_hash.ToArray()): key = StorageKey(script_hash=hash, key=key[20:]) to_add.append((key.ToArray(), item)) for k, v in to_add: self.Snapshot.Storages.Add(k, v) engine.CurrentContext.EvaluationStack.PushT( StackItem.FromInterface(contract)) self.events_to_dispatch.append( SmartContractEvent(SmartContractEvent.CONTRACT_MIGRATED, ContractParameter( ContractParameterType.InteropInterface, contract), hash, GetBlockchain().Height + 1, engine.ScriptContainer.Hash if engine.ScriptContainer else None, test_mode=engine.testMode)) return self.Contract_Destroy(engine)
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