Example #1
0
    def SearchContracts(self, query):
        res = []
        sn = self._db.snapshot()
        contracts = DBCollection(self._db, sn, DBPrefix.ST_Contract, ContractState)
        keys = contracts.Keys

        query = query.casefold()

        for item in keys:

            contract = contracts.TryGet(keyval=item)
            try:
                if query in contract.Name.decode('utf-8').casefold():
                    res.append(contract)
                elif query in contract.Author.decode('utf-8').casefold():
                    res.append(contract)
                elif query in contract.Description.decode('utf-8').casefold():
                    res.append(contract)
                elif query in contract.Email.decode('utf-8').casefold():
                    res.append(contract)
            except Exception as e:
                logger.info("Could not query contract: %s " % e)

        sn.close()

        return res
    def test_contract_create_block(self):

        hexdata = binascii.unhexlify(self.contract_create_block)

        block = Helper.AsSerializableWithType(hexdata, 'neo.Core.Block.Block')

        self.assertEqual(block.Index, self.contract_block_index)

        result = Blockchain.Default().Persist(block)

        self.assertTrue(result)

        contracts = DBCollection(Blockchain.Default()._db, DBPrefix.ST_Contract, ContractState)

        contract_added = contracts.TryGet(self.contract_hash)

        self.assertIsNotNone(contract_added)

        self.assertEqual(contract_added.HasStorage, False)
        self.assertEqual(contract_added.Name, b'test')
        self.assertEqual(contract_added.Email, b'test')

        self.assertEqual(len(Blockchain.Default().SearchContracts("test NEX Template V3")), 1)
        self.assertEqual(len(Blockchain.Default().SearchContracts("TEST nex TEMPLATE v3")), 1)
        self.assertEqual(len(Blockchain.Default().SearchContracts("TEST!")), 0)

        code = contract_added.Code

        self.assertIsNotNone(code)

        self.assertEqual(code.ReturnType, 2)

        self.assertEqual(code.ScriptHash().ToBytes(), self.contract_hash)
        self.assertEqual(code.Script.hex().encode('utf-8'), self.contract_block_script)
    def test_invocation_assetcreate_block(self):

        hexdata = binascii.unhexlify(self.asset_create_block)

        block = Helper.AsSerializableWithType(hexdata, 'neo.Core.Block.Block')

        self.assertEqual(block.Index, self.asset_create_index)

        result = Blockchain.Default().Persist(block)

        self.assertTrue(result)

        # now the asset that was created should be there
        assets = DBCollection(Blockchain.Default()._db, DBPrefix.ST_Asset, AssetState)

        newasset = assets.TryGet(self.asset_create_id)

        self.assertIsNotNone(newasset)

        self.assertEqual(newasset.AssetType, 1)
        self.assertEqual(newasset.Precision, 8)
        self.assertEqual(Crypto.ToAddress(newasset.Admin), self.asset_admin)
        self.assertEqual(Crypto.ToAddress(newasset.Issuer), self.asset_admin)
        self.assertIsInstance(newasset.AssetId, UInt256)
        self.assertEqual(newasset.AssetId.ToBytes(), self.asset_create_id)
Example #4
0
    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)

        return coins.TryGet(keyval=tx_hash)
Example #5
0
    def GetContract(self, hash):

        if type(hash) is str:
            try:
                hash = UInt160.ParseString(hash).ToBytes()
            except Exception as e:
                logger.info("could not convert argument to bytes :%s " % e)
                return None

        contracts = DBCollection(self._db, DBPrefix.ST_Contract, ContractState)
        contract = contracts.TryGet(keyval=hash)
        return contract
Example #6
0
    def GetAccountState(self, address, print_all_accounts=False):

        if type(address) is str:
            try:
                address = address.encode('utf-8')
            except Exception as e:
                logger.info("could not convert argument to bytes :%s " % e)
                return None

        accounts = DBCollection(self._db, DBPrefix.ST_Account, AccountState)
        acct = accounts.TryGet(keyval=address)

        return acct
Example #7
0
    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

        assets = DBCollection(self._db, DBPrefix.ST_Asset, AssetState)
        asset = assets.TryGet(assetId)

        return asset
    def GetContract(self, hash):

        if type(hash) is str:
            try:
                hash = hash.encode('utf-8')
            except Exception as e:
                self.__log.debug("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
Example #9
0
    def GetAssetState(self, assetId):

        if type(assetId) is str:
            try:
                assetId = assetId.encode('utf-8')
            except Exception as e:
                self.__log.debug("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
Example #10
0
    def GetAllUnspent(self, hash):

        unspents = []

        unspentcoins = DBCollection(self._db, 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
Example #11
0
    def SearchAssetState(self, query):
        res = []
        assets = DBCollection(self._db, 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)

        return res
Example #12
0
    def GetUnspent(self, hash, index):

        coins = DBCollection(self._db, DBPrefix.ST_Coin, 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]
Example #13
0
    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
Example #14
0
    def GetUnclaimed(self, hash):

        tx, height = self.GetTransaction(hash)

        if tx is None:
            return None

        out = {}
        coins = DBCollection(self._db, 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)

        return out
Example #15
0
    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:
                self.__log.debug("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()

        if acct is None:
            print("Could not find account. Length of accounts %s " % len(accounts.Collection.keys()))
            if print_all_accounts:
                print("All accounts: %s " % accounts.Collection.keys())
        return acct
Example #16
0
    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)
            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)

        sn.close()

        return res
Example #17
0
    def SearchAssetState(self, query):
        res = []
        assets = DBCollection(self._db, DBPrefix.ST_Asset, AssetState)
        keys = assets.Keys

        if query.lower() == "neo":
            query = "AntShare"

        if query.lower() in {"gas", "neogas"}:
            query = "AntCoin"

        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)

        return res
Example #18
0
    def test_contract_create_block(self):
        return

        hexdata = binascii.unhexlify(self.contract_create_block)

        block = Helper.AsSerializableWithType(hexdata, 'neo.Core.Block.Block')

        self.assertEqual(block.Index, self.contract_block_index)

        result = Blockchain.Default().Persist(block)

        self.assertTrue(result)

        snapshot = Blockchain.Default()._db.snapshot()

        contracts = DBCollection(Blockchain.Default()._db, snapshot,
                                 DBPrefix.ST_Contract, ContractState)

        contract_added = contracts.TryGet(self.contract_hash)

        self.assertIsNotNone(contract_added)

        self.assertEqual(contract_added.HasStorage, False)
        self.assertEqual(contract_added.Name, b'test create')
        self.assertEqual(contract_added.Email, b'*****@*****.**')

        code = contract_added.Code

        self.assertIsNotNone(code)

        self.assertEqual(code.ReturnType, 255)

        self.assertEqual(code.ScriptHash().ToBytes(), self.contract_hash)
        self.assertEqual(code.Script.hex().encode('utf-8'),
                         self.contract_block_script)

        snapshot.close()
Example #19
0
    def Persist(self, block):

        start = time.clock()

        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')
        self.__log.debug("[BlockFee] : %s %s " % (block.Index, amount_sysfee))

        try:
            with self._db.write_batch() as wb:

                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:

                        #                        print("RUNNING INVOCATION TRASACTION!!!!!! %s %s " % (block.Index, tx.Hash.ToBytes()))
                        print("[neo.Implementations.Blockchains.LevelDBBlockchain.PersistBlock: Invoke tx] -> index, tx hash %s %s " % (block.Index, tx.Hash.ToBytes()))
                        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:
                            # drum roll?
                            success = engine.Execute()
                            print("[neo.Implementations.Blockchains.LevelDBBlockchain.PersistBlock: engine execute] -> Success")
                            if success:
                                service.Commit()

                                if len(service.notifications) > 0:
                                    for n in service.notifications:
                                        self.OnNotify(n)

                            for item in engine.EvaluationStack.Items:
                                print("[neo.Implementations.Blockchains.LevelDBBlockchain.PersistBlock: engine execute result] -> %s " % item)

                        except Exception as e:
                            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:
                            self.__log.debug("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():
                    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._current_block_height = block.Index

                end = time.clock()
                self.__log.debug("PERSISTING BLOCK %s (cache) %s %s " % (block.Index, len(self._block_cache), end - start))
        except Exception as e:
            print("couldnt persist block %s " % e)
Example #20
0
    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')

        to_dispatch = []

        with self._db.write_batch() as wb:

            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.StateTransaction:
                    # @TODO Implement persistence for State Descriptors
                    pass

                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)

                    to_dispatch = to_dispatch + service.events_to_dispatch
                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)

            sn.close()

            wb.put(DBPrefix.SYS_CurrentBlock, block.Hash.ToBytes() + block.IndexBytes())
            self._current_block_height = block.Index
            self._persisting_block = None

            self.TXProcessed += len(block.Transactions)

        for event in to_dispatch:
            events.emit(event.event_type, event)
Example #21
0
 def GetStorageItem(self, storage_key):
     sn = self._db.snapshot()
     storages = DBCollection(self._db, sn, DBPrefix.ST_Storage, StorageItem)
     item = storages.TryGet(storage_key.ToArray())
     sn.close()
     return item
Example #22
0
 def GetStorageItem(self, storage_key):
     storages = DBCollection(self._db, DBPrefix.ST_Storage, StorageItem)
     item = storages.TryGet(storage_key.ToArray())
     return item
Example #23
0
    def Persist(self, block):

        accounts = DBCollection(self._db, DBPrefix.ST_Account, AccountState)
        unspentcoins = DBCollection(self._db, DBPrefix.ST_Coin,
                                    UnspentCoinState)
        spentcoins = DBCollection(self._db, DBPrefix.ST_SpentCoin,
                                  SpentCoinState)
        assets = DBCollection(self._db, DBPrefix.ST_Asset, AssetState)
        validators = DBCollection(self._db, DBPrefix.ST_Validator,
                                  ValidatorState)
        contracts = DBCollection(self._db, DBPrefix.ST_Contract, ContractState)
        storages = DBCollection(self._db, 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:
            for tx in block.Transactions:

                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:

                    validator = validators.GetAndChange(
                        tx.PublicKey, ValidatorState(pub_key=tx.PublicKey))
                    #                        logger.info("VALIDATOR %s " % validator.ToJson())

                elif tx.Type == TransactionType.StateTransaction:
                    # @TODO Implement persistence for State Descriptors
                    pass

                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=wb)

                    engine = ApplicationEngine(
                        trigger_type=TriggerType.Application,
                        container=tx,
                        table=script_table,
                        service=service,
                        gas=tx.Gas,
                        testMode=True)

                    engine.LoadScript(tx.Script)

                    # normally, this function does not return true/false
                    # for testing purposes, we try to execute and if an exception is raised
                    # we will return false, otherwise if success return true

                    # this is different than the 'success' bool returned by engine.Execute()
                    # the 'success' bool returned by engine.Execute() is a value indicating
                    # wether or not the invocation was successful, and if so, we then commit
                    # the changes made by the contract to the database
                    try:
                        success = engine.Execute()
                        # service.ExecutionCompleted(engine, success)
                        return True
                    except Exception as e:
                        # service.ExecutionCompleted(self, False, e)
                        return False
Example #24
0
    def GetContract(self, hash):

        sn = self._db.snapshot()
        contracts = DBCollection(self._db, sn, DBPrefix.ST_Contract, ContractState)
        sn.close()
        return contracts.TryGet(keyval=hash)
Example #25
0
 def GetAssetState(self, assetId):
     sn = self._db.snapshot()
     assets = DBCollection(self._db, sn, DBPrefix.ST_Asset, AssetState)
     asset = assets.TryGet(assetId)
     return asset