def clone_from_live(self): print("cloining from live!") clone_db = GetBlockchain()._db.snapshot() for key, value in clone_db.iterator(prefix=DBPrefix.ST_Storage, include_value=True): self._db.put(key, value) print("cloned db")
def Blockchain_GetHeight(self, engine: ExecutionEngine): if GetBlockchain() is None: engine.CurrentContext.EvaluationStack.PushT(0) else: engine.CurrentContext.EvaluationStack.PushT(GetBlockchain().Height) return True
def NetworkFee(self): """ Get the network fee. Returns: Fixed8: """ if self.__network_fee is None: input = Fixed8(0) for coin_ref in self.References.values(): if coin_ref.AssetId == GetBlockchain().SystemCoin().Hash: input = input + coin_ref.Value output = Fixed8(0) for tx_output in self.outputs: if tx_output.AssetId == GetBlockchain().SystemCoin().Hash: output = output + tx_output.Value self.__network_fee = input - output - self.SystemFee() # logger.info("Determined network fee to be %s " % (self.__network_fee.value)) return self.__network_fee
def FromTrimmedData(byts): """ Deserialize a block from raw bytes. Args: byts: Returns: Block: """ block = Block() block.__is_trimmed = True ms = StreamManager.GetStream(byts) reader = BinaryReader(ms) block.DeserializeUnsigned(reader) reader.ReadByte() witness = Witness() witness.Deserialize(reader) block.Script = witness bc = GetBlockchain() tx_list = [] for tx_hash in reader.ReadHashes(): tx = bc.GetTransaction(tx_hash)[0] if not tx: raise Exception("Could not find transaction!\n Are you running code against a valid Blockchain instance?\n Tests that accesses transactions or size of a block but inherit from NeoTestCase instead of BlockchainFixtureTestCase will not work.") tx_list.append(tx) block.Transactions = tx_list StreamManager.ReleaseStream(ms) return block
def Verify(self): """ Verify block using the verification script. Returns: bool: True if valid. False otherwise. """ if not self.Hash.ToBytes() == GetGenesis().Hash.ToBytes(): return False bc = GetBlockchain() if not bc.ContainsBlock(self.Index): return False if self.Index > 0: prev_header = GetBlockchain().GetHeader(self.PrevHash.ToBytes()) if prev_header is None: return False if prev_header.Index + 1 != self.Index: return False if prev_header.Timestamp >= self.Timestamp: return False # this should be done to actually verify the block if not Helper.VerifyScripts(self): return False return True
def Verify(self): if not self.Hash.ToBytes() == GetGenesis().Hash.ToBytes(): return False bc = GetBlockchain() if not bc.ContainsBlock(self.Index): return False if self.Index > 0: prev_header = GetBlockchain().GetHeader(self.PrevHash.ToBytes()) if prev_header is None: return False if prev_header.Index + 1 != self.Index: return False if prev_header.Timestamp >= self.Timestamp: return False # this should be done to actually verify the block if not Helper.VerifyScripts(self): return False return True
def Verify(self): print("verifying block base 1") if not self.Hash.ToBytes() == GetGenesis().Hash.ToBytes(): return False print("verifying block base @ %s " % self.Index) bc = GetBlockchain() print("BC: %s " % bc) if not bc.ContainsBlock(self.Index): print("blockchin didnt contain block index") return False print("verifying block base 3 %s " % self.PrevHash.ToBytes()) if self.Index > 0: prev_header = GetBlockchain().GetHeader(self.PrevHash.ToBytes()) if prev_header == None: return False if prev_header.Index + 1 != self.Index: return False if prev_header.Timestamp >= self.Timestamp: return False print("Will verify scripts!!") #this should be done to actually verify the block if not Helper.VerifyScripts(self): print("could not verify scripts") return False return True
def Verify(self, completely=False): self.__log.debug("Verifying BLOCK!!") from neo.Blockchain import GetBlockchain,GetConsensusAddress res = super(Block, self).Verify() if not res: return False #first TX has to be a miner transaction. other tx after that cant be miner tx if self.Transactions[0].Type != TransactionType.MinerTransaction: return False for tx in self.Transactions[1:]: if tx.Type == TransactionType.MinerTransaction: return False if completely: bc = GetBlockchain() if self.NextConsensus != GetConsensusAddress(bc.GetValidators(self.Transactions).ToArray()): return False for tx in self.Transactions: if not tx.Verify(): pass self.__log.debug("Blocks cannot be fully validated at this moment. please pass completely=False") raise NotImplementedError() ## do this below! #foreach(Transaction tx in Transactions) #if (!tx.Verify(Transactions.Where(p = > !p.Hash.Equals(tx.Hash)))) return false; #Transaction tx_gen = Transactions.FirstOrDefault(p= > p.Type == TransactionType.MinerTransaction); #if (tx_gen?.Outputs.Sum(p = > p.Value) != CalculateNetFee(Transactions)) return false; return True
def Blockchain_GetTransactionHeight(self, engine: ExecutionEngine): data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray() height = -1 if GetBlockchain() is not None: tx, height = GetBlockchain().GetTransaction(UInt256(data=data)) engine.CurrentContext.EvaluationStack.PushT(height) return True
def Runtime_GetCurrentTime(self, engine: ExecutionEngine): if self.Snapshot.PersistingBlock is None: BC = GetBlockchain() header = BC.GetHeaderByHeight(BC.Height) engine.CurrentContext.EvaluationStack.PushT( header.Timestamp + GetBlockchain().SECONDS_PER_BLOCK) else: engine.CurrentContext.EvaluationStack.PushT( self.Snapshot.PersistingBlock.Timestamp) return True
def Blockchain_GetTransaction(self, engine: ExecutionEngine): data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray() tx = None if GetBlockchain() is not None: tx, height = GetBlockchain().GetTransaction(UInt256(data=data)) engine.CurrentContext.EvaluationStack.PushT( StackItem.FromInterface(tx)) return True
def TestInvokeContract(wallet, args, withdrawal_tx=None, from_addr=None, min_fee=DEFAULT_MIN_FEE, invoke_attrs=None, owners=None): BC = GetBlockchain() contract = BC.GetContract(args[0]) if contract: # params = args[1:] if len(args) > 1 else [] params, neo_to_attach, gas_to_attach = PromptUtils.get_asset_attachments(params) params, parse_addresses = PromptUtils.get_parse_addresses(params) params.reverse() if '--i' in params: params = [] for index, iarg in enumerate(contract.Code.ParameterList): param, abort = PromptUtils.gather_param(index, iarg) if abort: return None, None, None, None, False params.append(param) params.reverse() sb = ScriptBuilder() for p in params: process_params(sb, p, wallet, parse_addresses) sb.EmitAppCall(contract.Code.ScriptHash().Data) out = sb.ToArray() outputs = [] if neo_to_attach: output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash, Value=neo_to_attach, script_hash=contract.Code.ScriptHash(), ) outputs.append(output) if gas_to_attach: output = TransactionOutput(AssetId=Blockchain.SystemCoin().Hash, Value=gas_to_attach, script_hash=contract.Code.ScriptHash()) outputs.append(output) return test_invoke(out, wallet, outputs, withdrawal_tx, from_addr, min_fee, invoke_attrs=invoke_attrs, owners=owners) else: print("Contract %s not found" % args[0]) return None, None, None, None, False
def Verify(self): if self.Hash == GetGenesis().Hash: return True if GetBlockchain().ContainsBlock(self.Hash): return True prev_header = GetBlockchain().GetHeader(self.PrevHash) if prev_header == None: return False if prev_header.Index + 1 != self.Index: return False if prev_header.Timestamp >= self.Timestamp: return False self.__log.debug("End verify for now. cannot verify scripts at the moment") return True
def Runtime_Log(self, engine: ExecutionEngine): item = engine.CurrentContext.EvaluationStack.Pop() # will raise an exception for types that don't support it item.GetByteArray() # if we pass we can call the convenience method to pretty print the data message = item.GetString() hash = UInt160(data=engine.CurrentContext.ScriptHash()) tx_hash = None if engine.ScriptContainer: tx_hash = engine.ScriptContainer.Hash engine.write_log(str(message)) # Build and emit smart contract event self.events_to_dispatch.append( SmartContractEvent(SmartContractEvent.RUNTIME_LOG, ContractParameter(ContractParameterType.String, value=message), hash, GetBlockchain().Height + 1, tx_hash, test_mode=engine.testMode)) return True
def Contract_Destroy(self, engine): hash = UInt160(data=engine.CurrentContext.ScriptHash()) contract = self.Snapshot.Contracts.TryGet(hash.ToBytes()) if contract is not None: self.Snapshot.Contracts.Delete(hash.ToBytes()) if contract.HasStorage: to_del = [] for k, v in self.Snapshot.Storages.Find(hash.ToArray()): storage_key = StorageKey(script_hash=hash, key=k[20:]) # Snapshot.Storages.Delete() modifies the underlying dictionary of the cache we'd be iterating # over using Storages.Find. We therefore need to postpone deletion to_del.append(storage_key) for storage_key in to_del: self.Snapshot.Storages.Delete(storage_key.ToArray()) self.events_to_dispatch.append( SmartContractEvent(SmartContractEvent.CONTRACT_DESTROY, ContractParameter( ContractParameterType.InteropInterface, contract), hash, GetBlockchain().Height + 1, engine.ScriptContainer.Hash if engine.ScriptContainer else None, test_mode=engine.testMode)) return True
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): 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: 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) return False Helper.EmitServiceEvents(state_reader) return True
def FullTransactions(self): """ Get the list of full Transaction objects. Note: Transactions can be trimmed to contain only the header and the hash. This will get the full data if trimmed transactions are found. Returns: list: of neo.Core.TX.Transaction.Transaction objects. """ is_trimmed = False try: tx = self.Transactions[0] if type(tx) is str: is_trimmed = True except Exception as e: pass if not is_trimmed: return self.Transactions txs = [] for hash in self.Transactions: tx, height = GetBlockchain().GetTransaction(hash) txs.append(tx) self.Transactions = txs return self.Transactions
def test_Storage2(self): output = Compiler.instance().load('%s/boa_test/example/blockchain/StorageTest.py' % TestContract.dirname).default out = output.write() snapshot = GetBlockchain()._db.createSnapshot() tx, results, total_ops, engine = TestBuild(out, ['sget', 100, 10000000000], self.GetWallet1(), '070505', '05', snapshot=snapshot) self.assertEqual(len(results), 1) self.assertEqual(results[0].GetByteArray(), b'') tx, results, total_ops, engine = TestBuild(out, ['sput', 100, 10000000000], self.GetWallet1(), '070505', '05', snapshot=snapshot) self.assertEqual(len(results), 1) self.assertEqual(results[0].GetByteArray(), b'\x01') tx, results, total_ops, engine = TestBuild(out, ['sget', 100, 10000000000], self.GetWallet1(), '070505', '05', snapshot=snapshot) self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 10000000000) tx, results, total_ops, engine = TestBuild(out, ['sdel', 100, 10000000000], self.GetWallet1(), '070505', '05', snapshot=snapshot) self.assertEqual(len(results), 1) self.assertEqual(results[0].GetByteArray(), b'\x01') tx, results, total_ops, engine = TestBuild(out, ['sget', 100, 10000000000], self.GetWallet1(), '070505', '05', snapshot=snapshot) self.assertEqual(len(results), 1) self.assertEqual(results[0].GetByteArray(), b'')
def Storage_Delete(self, engine: ExecutionEngine): if self.Trigger != TriggerType.Application and self.Trigger != TriggerType.ApplicationR: return False context = engine.CurrentContext.EvaluationStack.Pop().GetInterface( neo.SmartContract.StorageContext.StorageContext) if not self.CheckStorageContext(context): return False if context.IsReadOnly: return False key = engine.CurrentContext.EvaluationStack.Pop().GetByteArray() storage_key = StorageKey(script_hash=context.ScriptHash, key=key) if type(engine) == ExecutionEngine: test_mode = False else: test_mode = engine.testMode self.events_to_dispatch.append( SmartContractEvent(SmartContractEvent.STORAGE_DELETE, ContractParameter(ContractParameterType.String, key), context.ScriptHash, GetBlockchain().Height + 1, engine.ScriptContainer.Hash if engine.ScriptContainer else None, test_mode=test_mode)) item = self.Snapshot.Storages.TryGet(storage_key.ToArray()) if item and item.IsConstant: return False self.Snapshot.Storages.Delete(storage_key.ToArray()) return True
def Blockchain_GetHeader(self, engine: ExecutionEngine): data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray() header = None if len(data) <= 5: height = BigInteger.FromBytes(data) if GetBlockchain() is not None: header = GetBlockchain().GetHeaderBy(height_or_hash=height) elif height == 0: header = GetBlockchain().GenesisBlock().Header elif len(data) == 32: hash = UInt256(data=data) if GetBlockchain() is not None: header = GetBlockchain().GetHeaderBy(height_or_hash=hash) elif hash == GetBlockchain().GenesisBlock().Hash: header = GetBlockchain().GenesisBlock().Header engine.CurrentContext.EvaluationStack.PushT( StackItem.FromInterface(header)) return True
def get_invoke_result(self, script): snapshot = GetBlockchain()._db.createSnapshot() appengine = ApplicationEngine.Run(snapshot, script=script) return { "script": script.decode('utf-8'), "state": VMStateStr(appengine.State), "gas_consumed": appengine.GasConsumed().ToString(), "stack": [ContractParameter.ToParameter(item).ToJson() for item in appengine.ResultStack.Items] }
def GetScriptHashesForVerifying(self): #if this is the genesis block, we dont have a prev hash! if self.PrevHash == bytearray(32): return [self.Script.VerificationScript.ToScriptHash()] prev_header = GetBlockchain().GetHeader(self.PrevHash) if prev_header == None: raise Exception('Invalid operation') return [prev_header.NextConsensus]
def ToJson(self): json = super(Block, self).ToJson() if self.__is_trimmed: json['tx'] = self.Transactions else: json['tx'] = [tx.ToJson() for tx in self.Transactions] json['sys_fee'] = GetBlockchain().GetSysFeeAmount(self.Hash) return json
def Verify(self, completely=False): """ Verify the integrity of the block. Args: completely: (Not functional at this time). Returns: bool: True if valid. False otherwise. """ res = super(Block, self).Verify() if not res: return False from neo.Blockchain import GetBlockchain, GetConsensusAddress # first TX has to be a miner transaction. other tx after that cant be miner tx if self.Transactions[0].Type != TransactionType.MinerTransaction: return False for tx in self.Transactions[1:]: if tx.Type == TransactionType.MinerTransaction: return False if completely: bc = GetBlockchain() if self.NextConsensus != GetConsensusAddress( bc.GetValidators(self.Transactions).ToArray()): return False for tx in self.Transactions: if not tx.Verify(): pass logger.error( "Blocks cannot be fully validated at this moment. please pass completely=False" ) raise NotImplementedError() # do this below! # foreach(Transaction tx in Transactions) # if (!tx.Verify(Transactions.Where(p = > !p.Hash.Equals(tx.Hash)))) return false; # Transaction tx_gen = Transactions.FirstOrDefault(p= > p.Type == TransactionType.MinerTransaction); # if (tx_gen?.Outputs.Sum(p = > p.Value) != CalculateNetFee(Transactions)) return false; return True
def __init__(self, verifiable, isMultiSig=False): self.Verifiable = verifiable if verifiable.raw_tx: self.ScriptHashes = verifiable.GetScriptHashesForVerifying() else: self.ScriptHashes = verifiable.GetScriptHashesForVerifying( GetBlockchain()._db.createSnapshot()) self.ContextItems = {} self.IsMultiSig = isMultiSig
def __init__(self): try: self._db = GetBlockchain().Default().GetDB().cloneDatabaseStorage( DBFactory.getDebugStorageDB()) except Exception as e: logger.info( "DEBUG leveldb unavailable, you may already be running this process: %s " % e) raise Exception('DEBUG Leveldb Unavailable %s ' % e)
def TestInvokeContract(wallet, args): BC = GetBlockchain() contract = BC.GetContract(args[0]) if contract: descripe_contract(contract) verbose = False if 'verbose' in args: verbose = True args.remove('verbose') print("VERBOSE %s " % verbose) params = args[1:] if len(args) > 1 else [] if len(params) > 0 and params[0] == 'describe': return params.reverse() sb = ScriptBuilder() for p in params: item = parse_param(p) sb.push(item) sb.EmitAppCall(contract.Code.ScriptHash().Data) out = sb.ToArray() return test_invoke(out, wallet) else: print("Contract %s not found" % args[0]) return None, None
def Blockchain_GetAsset(self, engine: ExecutionEngine): data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray() asset = None if GetBlockchain() is not None: asset = self.Snapshot.Assets.TryGet(UInt256(data=data)) if asset is None: return False engine.CurrentContext.EvaluationStack.PushT( StackItem.FromInterface(asset)) return True
def test_GetScriptHashesForVerifying_invalid_operation(self): # test a normal tx with a bad assetId ms = MemoryStream(binascii.unhexlify(self.rtx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) snapshot = GetBlockchain()._db.createSnapshot() with self.assertRaises(Exception) as e: tx.GetScriptHashesForVerifying(snapshot) self.assertTrue("Invalid operation" in str(e.exception)) # test a raw tx with a bad assetId ms = MemoryStream(binascii.unhexlify(self.rtx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) tx.raw_tx = True snapshot = GetBlockchain()._db.createSnapshot() with self.assertRaises(Exception) as e: tx.GetScriptHashesForVerifying(snapshot) self.assertTrue("Invalid operation" in str(e.exception))
def Transaction_GetUnspentCoins(self, engine: ExecutionEngine): tx = engine.CurrentContext.EvaluationStack.Pop().GetInterface( Transaction) if tx is None: return False outputs = GetBlockchain().GetAllUnspent(tx.Hash) if len(outputs) > engine.maxArraySize: return False refs = [StackItem.FromInterface(unspent) for unspent in outputs] engine.CurrentContext.EvaluationStack.PushT(refs) return True
def clone_from_live(self): clone_db = GetBlockchain()._db.snapshot() for key, value in clone_db.iterator(prefix=DBPrefix.ST_Storage, include_value=True): self._db.put(key, value)