def SearchContracts(self, query): res = [] sn = self._db.snapshot() contracts = DBCollection(self._db, sn, DBPrefix.ST_Contract, ContractState) keys = contracts.Keys for item in keys: contract = contracts.TryGet(keyval=item) try: if query in contract.Name.decode('utf-8'): res.append(contract) elif query in contract.Author.decode('utf-8'): res.append(contract) elif query in contract.Description.decode('utf-8'): res.append(contract) elif query in contract.Email.decode('utf-8'): res.append(contract) except Exception as e: logger.info("Could not query contract: %s " % e) sn.close() return res
def GetAssetState(self, assetId): if type(assetId) is str: try: assetId = assetId.encode('utf-8') except Exception as e: logger.info("could not convert argument to bytes :%s " % e) return None sn = self._db.snapshot() assets = DBCollection(self._db, sn, DBPrefix.ST_Asset, AssetState) asset = assets.TryGet(assetId) return asset
def GetSpentCoins(self, tx_hash): if type(tx_hash) is not bytes: tx_hash = bytes(tx_hash.encode('utf-8')) sn = self._db.snapshot() coins = DBCollection(self._db, sn, DBPrefix.ST_SpentCoin, SpentCoinState) result = coins.TryGet(keyval=tx_hash) sn.close() return result
def GetContract(self, hash): if type(hash) is str: try: hash = hash.encode('utf-8') except Exception as e: logger.info("could not convert argument to bytes :%s " % e) return None sn = self._db.snapshot() contracts = DBCollection(self._db, sn, DBPrefix.ST_Contract, ContractState) contract = contracts.TryGet(keyval=hash) sn.close() return contract
def SearchAssetState(self, query): res = [] sn = self._db.snapshot() assets = DBCollection(self._db, sn, DBPrefix.ST_Asset, AssetState) keys = assets.Keys for item in keys: asset = assets.TryGet(keyval=item) if query in asset.Name.decode('utf-8'): res.append(asset) elif query in Crypto.ToAddress(asset.Issuer): res.append(asset) elif query in Crypto.ToAddress(asset.Admin): res.append(asset) sn.close() return res
def GetUnspent(self, hash, index): sn = self._db.snapshot() coins = DBCollection(self._db, sn, DBPrefix.ST_SpentCoin, UnspentCoinState) state = coins.TryGet(hash) if state is None: return None if index >= len(state.Items): return None if state.Items[index] & CoinState.Spent > 0: return None tx, height = self.GetTransaction(hash) return tx.outputs[index]
def GetAccountState(self, script_hash, print_all_accounts=False): if type(script_hash) is str: try: script_hash = script_hash.encode('utf-8') except Exception as e: logger.info("could not convert argument to bytes :%s " % e) return None sn = self._db.snapshot() accounts = DBCollection(self._db, sn, DBPrefix.ST_Account, AccountState) acct = accounts.TryGet(keyval=script_hash) sn.close() return acct
def GetAllUnspent(self, hash): unspents = [] sn = self._db.snapshot() unspentcoins = DBCollection(self._db, sn, DBPrefix.ST_Coin, UnspentCoinState) state = unspentcoins.TryGet(keyval=hash.ToBytes()) if state: tx, height = self.GetTransaction(hash) for index, item in enumerate(state.Items): if item & CoinState.Spent == 0: unspents.append(tx.outputs[index]) return unspents
def GetUnclaimed(self, hash): tx, height = self.GetTransaction(hash) if tx is None: return None out = {} sn = self._db.snapshot() coins = DBCollection(self._db, sn, DBPrefix.ST_SpentCoin, SpentCoinState) state = coins.TryGet(keyval=hash.ToBytes()) if state: for item in state.Items: out[item.index] = SpentCoin(tx.outputs[item.index], height, item.height) sn.close() return out
def Persist(self, block): self._persisting_block = block sn = self._db.snapshot() accounts = DBCollection(self._db, sn, DBPrefix.ST_Account, AccountState) unspentcoins = DBCollection(self._db, sn, DBPrefix.ST_Coin, UnspentCoinState) spentcoins = DBCollection(self._db, sn, DBPrefix.ST_SpentCoin, SpentCoinState) assets = DBCollection(self._db, sn, DBPrefix.ST_Asset, AssetState) validators = DBCollection(self._db, sn, DBPrefix.ST_Validator, ValidatorState) contracts = DBCollection(self._db, sn, DBPrefix.ST_Contract, ContractState) storages = DBCollection(self._db, sn, DBPrefix.ST_Storage, StorageItem) amount_sysfee = self.GetSysFeeAmount( block.PrevHash) + block.TotalFees().value amount_sysfee_bytes = amount_sysfee.to_bytes(8, 'little') # with self._db.write_batch() as wb: wb = rocksdb.WriteBatch() wb.put(DBPrefix.DATA_Block + block.Hash.ToBytes(), amount_sysfee_bytes + block.Trim()) for tx in block.Transactions: wb.put(DBPrefix.DATA_Transaction + tx.Hash.ToBytes(), block.IndexBytes() + tx.ToArray()) # go through all outputs and add unspent coins to them unspentcoinstate = UnspentCoinState.FromTXOutputsConfirmed( tx.outputs) unspentcoins.Add(tx.Hash.ToBytes(), unspentcoinstate) # go through all the accounts in the tx outputs for output in tx.outputs: account = accounts.GetAndChange( output.AddressBytes, AccountState(output.ScriptHash)) if account.HasBalance(output.AssetId): account.AddToBalance(output.AssetId, output.Value) else: account.SetBalanceFor(output.AssetId, output.Value) # go through all tx inputs unique_tx_input_hashes = [] for input in tx.inputs: if input.PrevHash not in unique_tx_input_hashes: unique_tx_input_hashes.append(input.PrevHash) for txhash in unique_tx_input_hashes: prevTx, height = self.GetTransaction(txhash.ToBytes()) coin_refs_by_hash = [ coinref for coinref in tx.inputs if coinref.PrevHash.ToBytes() == txhash.ToBytes() ] for input in coin_refs_by_hash: uns = unspentcoins.GetAndChange(input.PrevHash.ToBytes()) uns.OrEqValueForItemAt(input.PrevIndex, CoinState.Spent) if prevTx.outputs[input.PrevIndex].AssetId.ToBytes( ) == Blockchain.SystemShare().Hash.ToBytes(): sc = spentcoins.GetAndChange( input.PrevHash.ToBytes(), SpentCoinState(input.PrevHash, height, [])) sc.Items.append( SpentCoinItem(input.PrevIndex, block.Index)) output = prevTx.outputs[input.PrevIndex] acct = accounts.GetAndChange( prevTx.outputs[input.PrevIndex].AddressBytes, AccountState(output.ScriptHash)) assetid = prevTx.outputs[input.PrevIndex].AssetId acct.SubtractFromBalance( assetid, prevTx.outputs[input.PrevIndex].Value) # do a whole lotta stuff with tx here... if tx.Type == TransactionType.RegisterTransaction: asset = AssetState(tx.Hash, tx.AssetType, tx.Name, tx.Amount, Fixed8(0), tx.Precision, Fixed8(0), Fixed8(0), UInt160(data=bytearray(20)), tx.Owner, tx.Admin, tx.Admin, block.Index + 2 * 2000000, False) assets.Add(tx.Hash.ToBytes(), asset) elif tx.Type == TransactionType.IssueTransaction: txresults = [ result for result in tx.GetTransactionResults() if result.Amount.value < 0 ] for result in txresults: asset = assets.GetAndChange(result.AssetId.ToBytes()) asset.Available = asset.Available - result.Amount elif tx.Type == TransactionType.ClaimTransaction: for input in tx.Claims: sc = spentcoins.TryGet(input.PrevHash.ToBytes()) if sc and sc.HasIndex(input.PrevIndex): sc.DeleteIndex(input.PrevIndex) spentcoins.GetAndChange(input.PrevHash.ToBytes()) elif tx.Type == TransactionType.EnrollmentTransaction: newvalidator = ValidatorState(pub_key=tx.PublicKey) validators.GetAndChange(tx.PublicKey.ToBytes(), newvalidator) elif tx.Type == TransactionType.PublishTransaction: contract = ContractState(tx.Code, tx.NeedStorage, tx.Name, tx.CodeVersion, tx.Author, tx.Email, tx.Description) contracts.GetAndChange(tx.Code.ScriptHash().ToBytes(), contract) elif tx.Type == TransactionType.InvocationTransaction: script_table = CachedScriptTable(contracts) service = StateMachine(accounts, validators, assets, contracts, storages, wb) engine = ApplicationEngine( trigger_type=TriggerType.Application, container=tx, table=script_table, service=service, gas=tx.Gas, testMode=False) engine.LoadScript(tx.Script, False) try: success = engine.Execute() service.ExecutionCompleted(engine, success) except Exception as e: service.ExecutionCompleted(engine, False, e) else: if tx.Type != b'\x00' and tx.Type != 128: logger.info("TX Not Found %s " % tx.Type) # do save all the accounts, unspent, coins, validators, assets, etc # now sawe the current sys block # filter out accounts to delete then commit for key, account in accounts.Current.items(): if not account.IsFrozen and len( account.Votes) == 0 and account.AllBalancesZeroOrLess(): accounts.Remove(key) accounts.Commit(wb) # filte out unspent coins to delete then commit for key, unspent in unspentcoins.Current.items(): if unspent.IsAllSpent: unspentcoins.Remove(key) unspentcoins.Commit(wb) # filter out spent coins to delete then commit to db for key, spent in spentcoins.Current.items(): if len(spent.Items) == 0: spentcoins.Remove(key) spentcoins.Commit(wb) # commit validators validators.Commit(wb) # commit assets assets.Commit(wb) # commit contracts contracts.Commit(wb) # commit storages ( not implemented ) storages.Commit(wb) # sn.close() wb.put(DBPrefix.SYS_CurrentBlock, block.Hash.ToBytes() + block.IndexBytes()) self._db.write(wb) self._current_block_height = block.Index self._persisting_block = None
def GetStorageItem(self, storage_key): sn = self._db.snapshot() storages = DBCollection(self._db, sn, DBPrefix.ST_Storage, StorageItem) item = storages.TryGet(storage_key.GetHashCodeBytes()) sn.close() return item