示例#1
0
    def get_accountstate(self, request, key_wallet):
        request.setHeader('Content-Type', 'application/json')
        try:
            print(key_wallet)
            acct = Blockchain.Default().GetAccountState(key_wallet)
            print(acct.ToJson())
            if acct is None:
                try:
                    acct = AccountState(
                        script_hash=Helper.AddrStrToScriptHash(key_wallet))
                except Exception as e:
                    self.format_message(
                        "Could not get contract with hash %s because test" %
                        (key_wallet))

            acctString = json.dumps(acct.ToJson())
            acctString = acctString.replace(
                "0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b",
                "NEO")
            acctString = acctString.replace(
                "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7",
                "GAS")
            return json.dumps({'response': json.loads(acctString)})
        except Exception as e:
            return self.format_message(
                "Could not get contract with hash %s because %s " %
                (acct.ToJson(), e))

        return self.format_message(
            "Could not get contract with hash %s because test" % (key_wallet))
示例#2
0
    def test_accountstate_ToJson(self):

        hash = UInt160(data=self.ac2_h)
        account = AccountState(script_hash=hash)

        res = account.ToJson()

        self.assertEqual(res['address'], account.Address)
        self.assertEqual(res['script_hash'], str(hash))
示例#3
0
    def Blockchain_GetAccount(self, engine: ExecutionEngine):
        hash = UInt160(data=engine.CurrentContext.EvaluationStack.Pop().GetByteArray())
        address = Crypto.ToAddress(hash).encode('utf-8')

        account = self.Accounts.GetOrAdd(address, new_instance=AccountState(script_hash=hash))
        engine.CurrentContext.EvaluationStack.PushT(StackItem.FromInterface(account))
        return True
示例#4
0
    def test_account_2(self):

        hash = UInt160(data=self.ac2_h)
        account2 = AccountState(script_hash=hash)

        addr = account2.Address

        self.assertEqual(addr, self.ac2_a)

        input = binascii.unhexlify(self.assset)
        asset = AssetState.DeserializeFromDB(input)

        account2.AddToBalance(asset.AssetId, Fixed8(97800000000))

#        print("account 2 %s " % json.dumps(account2.ToJson(), indent=4))

        self.assertEqual(account2.BalanceFor(asset.AssetId), Fixed8(97800000000))

        input = binascii.unhexlify(self.ac1_out)
        account1 = AccountState.DeserializeFromDB(input)
示例#5
0
    def json_rpc_method_handler(self, method, params):

        if method == "getaccountstate":
            acct = Blockchain.Default().GetAccountState(params[0])
            if acct is None:
                try:
                    acct = AccountState(
                        script_hash=Helper.AddrStrToScriptHash(params[0]))
                except Exception as e:
                    raise JsonRpcError(
                        -2146233033,
                        "One of the identified items was in an invalid format."
                    )

            return acct.ToJson()

        elif method == "getassetstate":
            asset_id = UInt256.ParseString(params[0])
            asset = Blockchain.Default().GetAssetState(asset_id.ToBytes())
            if asset:
                return asset.ToJson()
            raise JsonRpcError(-100, "Unknown asset")

        elif method == "getbestblockhash":
            return '0x%s' % Blockchain.Default().CurrentHeaderHash.decode(
                'utf-8')

        elif method == "getblock":
            # this should work for either str or int
            block = Blockchain.Default().GetBlock(params[0])
            if not block:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_block_output(block, params)

        elif method == "getblockcount":
            return Blockchain.Default().Height + 1

        elif method == "getblockhash":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return '0x%s' % Blockchain.Default().GetBlockHash(
                    height).decode('utf-8')
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getblocksysfee":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return Blockchain.Default().GetSysFeeAmountByHeight(height)
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getconnectioncount":
            return len(NodeLeader.Instance().Peers)

        elif method == "getcontractstate":
            script_hash = UInt160.ParseString(params[0])
            contract = Blockchain.Default().GetContract(script_hash.ToBytes())
            if contract is None:
                raise JsonRpcError(-100, "Unknown contract")
            return contract.ToJson()

        elif method == "getrawmempool":
            return list(
                map(lambda hash: "0x%s" % hash.decode('utf-8'),
                    NodeLeader.Instance().MemPool.keys()))

        elif method == "getversion":
            return {
                "port": self.port,
                "nonce": NodeLeader.Instance().NodeId,
                "useragent": settings.VERSION_NAME
            }

        elif method == "getrawtransaction":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")
            return self.get_tx_output(tx, height, params)

        elif method == "getstorage":
            script_hash = UInt160.ParseString(params[0])
            key = binascii.unhexlify(params[1].encode('utf-8'))
            storage_key = StorageKey(script_hash=script_hash, key=key)
            storage_item = Blockchain.Default().GetStorageItem(storage_key)
            if storage_item:
                return storage_item.Value.hex()
            return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "invoke":
            shash = UInt160.ParseString(params[0])
            contract_parameters = [
                ContractParameter.FromJson(p) for p in params[1]
            ]
            sb = ScriptBuilder()
            sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokefunction":
            contract_parameters = []
            if len(params) > 2:
                contract_parameters = [
                    ContractParameter.FromJson(p).ToVM() for p in params[2]
                ]
            sb = ScriptBuilder()
            sb.EmitAppCallWithOperationAndArgs(UInt160.ParseString(params[0]),
                                               params[1], contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokescript":
            script = params[0].encode('utf-8')
            return self.get_invoke_result(script)

        elif method == "sendrawtransaction":
            tx_script = binascii.unhexlify(params[0].encode('utf-8'))
            transaction = Transaction.DeserializeFromBufer(tx_script)
            result = NodeLeader.Instance().Relay(transaction)
            return result

        elif method == "validateaddress":
            return self.validateaddress(params)

        elif method == "getpeers":
            return self.get_peers()

        elif method == "getbalance":
            if self.wallet:
                return self.get_balance(params)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getwalletheight":
            if self.wallet:
                return self.wallet.WalletHeight
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "listaddress":
            if self.wallet:
                return self.list_address()
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getnewaddress":
            if self.wallet:
                keys = self.wallet.CreateKey()
                account = Account.get(
                    PublicKeyHash=keys.PublicKeyHash.ToBytes())
                return account.contract_set[0].Address.ToString()
            else:
                raise JsonRpcError(-400, "Access denied.")

        raise JsonRpcError.methodNotFound()
示例#6
0
    def json_rpc_method_handler(self, method, params):

        if method == "getaccountstate":
            acct = Blockchain.Default().GetAccountState(params[0])
            if acct is None:
                try:
                    acct = AccountState(script_hash=Helper.AddrStrToScriptHash(params[0]))
                except Exception as e:
                    raise JsonRpcError(-2146233033, "One of the identified items was in an invalid format.")

            return acct.ToJson()

        elif method == "getassetstate":
            asset_id = UInt256.ParseString(params[0])
            asset = Blockchain.Default().GetAssetState(asset_id.ToBytes())
            if asset:
                return asset.ToJson()
            raise JsonRpcError(-100, "Unknown asset")

        elif method == "getbestblockhash":
            return '0x%s' % Blockchain.Default().CurrentHeaderHash.decode('utf-8')

        elif method == "getblock":
            # this should work for either str or int

            block = Blockchain.Default().GetBlock(params[0])
            if not block:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_block_output(block, params)

        elif method == "getblockcount":
            return Blockchain.Default().Height + 1

        elif method == "getblockhash":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return '0x%s' % Blockchain.Default().GetBlockHash(height).decode('utf-8')
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getblocksysfee":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return Blockchain.Default().GetSysFeeAmountByHeight(height)
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getconnectioncount":
            return len(NodeLeader.Instance().Peers)

        elif method == "getcontractstate":
            script_hash = UInt160.ParseString(params[0])
            contract = Blockchain.Default().GetContract(script_hash.ToBytes())
            if contract is None:
                raise JsonRpcError(-100, "Unknown contract")
            return contract.ToJson()

        elif method == "getrawmempool":
            return list(map(lambda hash: "0x%s" % hash.decode('utf-8'), NodeLeader.Instance().MemPool.keys()))

        elif method == "getversion":
            return {
                "port": self.port,
                "nonce": NodeLeader.Instance().NodeId,
                "useragent": settings.VERSION_NAME
            }

        elif method == "getrawtransaction":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")
            return self.get_tx_output(tx, height, params)

        elif method == "getstorage":
            script_hash = UInt160.ParseString(params[0])
            key = binascii.unhexlify(params[1].encode('utf-8'))
            storage_key = StorageKey(script_hash=script_hash, key=key)
            storage_item = Blockchain.Default().GetStorageItem(storage_key)
            if storage_item:
                return storage_item.Value.hex()
            return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "invoke":
            shash = UInt160.ParseString(params[0])
            contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokefunction":
            contract_parameters = []
            if len(params) > 2:
                contract_parameters = [ContractParameter.FromJson(p).ToVM() for p in params[2]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithOperationAndArgs(UInt160.ParseString(params[0]), params[1], contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokescript":
            script = params[0].encode('utf-8')
            return self.get_invoke_result(script)

        elif method == "sendrawtransaction":
            tx_script = binascii.unhexlify(params[0].encode('utf-8'))
            transaction = Transaction.DeserializeFromBufer(tx_script)
            result = NodeLeader.Instance().Relay(transaction)
            return result

        elif method == "mw_construct_send_tx":
            return MyWishMethods.construct_send_tx(self.wallet, params)

        elif method == "mw_construct_deploy_tx":
            return MyWishMethods.construct_deploy_tx(self.wallet, params)

        elif method == "mw_construct_invoke_tx":
            return MyWishMethods.construct_invoke_tx(self.wallet, params)

        elif method == "getapplicationlog":
            assert(all([x in '1234567890abcdefABCDEFxX' for x in params[0]])) # prevent traversal
            try:
                with open('/home/neo/neo-python/notis/' + params[0]) as f:
                    res =  [json.loads(x) for x in f.read().split('\n') if x]
                    return [{'name': x['notify_type'], 'contract': x['contract'], 'args': x['payload']} for x in res]
            except FileNotFoundError:
                return ([])

        elif method == "submitblock":
            raise NotImplementedError()

        elif method == "validateaddress":
            return self.validateaddress(params)

        elif method == "getpeers":
            return self.get_peers()

        raise JsonRpcError.methodNotFound()
示例#7
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)
示例#8
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
示例#9
0
    def test_account_state(self):
        hash = UInt160(data=self.shash)
        account = AccountState(script_hash=hash)

        addr = account.Address

        self.assertEqual(addr, self.saddr)

        input = binascii.unhexlify(self.assset)

        asset = AssetState.DeserializeFromDB(input)

        account.AddToBalance(asset.AssetId, Fixed8(2440000000))

        self.assertEqual(account.BalanceFor(asset.AssetId), Fixed8(2440000000))

        account.SubtractFromBalance(asset.AssetId, Fixed8(1220000000))

        self.assertEqual(account.BalanceFor(asset.AssetId), Fixed8(1220000000))

        self.assertEqual(account.HasBalance(asset.AssetId), True)

        sshare_hash = Blockchain.SystemShare().Hash

        account.SubtractFromBalance(sshare_hash, Fixed8(800000000))

        self.assertFalse(account.AllBalancesZeroOrLess())

        acct_json = account.ToJson()

        stream = StreamManager.GetStream()
        writer = BinaryWriter(stream)

        account.Serialize(writer)
        out = stream.ToArray()
        StreamManager.ReleaseStream(stream)

        input = binascii.unhexlify(out)
        newaccount = AccountState.DeserializeFromDB(input)

        self.assertEqual(acct_json, newaccount.ToJson())
示例#10
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)
def MonkeyPatchPersist(self, block, snapshot=None):

    if snapshot is None:
        snapshot = self._db.createSnapshot()
        snapshot.PersistingBlock = block

    amount_sysfee = self.GetSysFeeAmount(
        block.PrevHash) + (block.TotalFees().value / Fixed8.D)
    amount_sysfee_bytes = struct.pack("<d", amount_sysfee)

    with self._db.getBatch() as wb:
        for tx in block.Transactions:
            unspentcoinstate = UnspentCoinState.FromTXOutputsConfirmed(
                tx.outputs)
            snapshot.UnspentCoins.Add(tx.Hash.ToBytes(), unspentcoinstate)

            # go through all the accounts in the tx outputs
            for output in tx.outputs:
                account = snapshot.Accounts.GetAndChange(
                    output.AddressBytes,
                    lambda: 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:

                    snapshot.UnspentCoins.GetAndChange(
                        input.PrevHash.ToBytes()).Items[
                            input.PrevIndex] |= CoinState.Spent

                    if prevTx.outputs[input.PrevIndex].AssetId.ToBytes(
                    ) == Blockchain.SystemShare().Hash.ToBytes():
                        sc = snapshot.SpentCoins.GetAndChange(
                            input.PrevHash.ToBytes(),
                            lambda: SpentCoinState(input.PrevHash, height, []))
                        sc.Items.append(
                            SpentCoinItem(input.PrevIndex, block.Index))

                    output = prevTx.outputs[input.PrevIndex]
                    acct = snapshot.Accounts.GetAndChange(
                        prevTx.outputs[input.PrevIndex].AddressBytes,
                        lambda: 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)

                snapshot.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 = snapshot.Assets.GetAndChange(
                        result.AssetId.ToBytes())
                    asset.Available = asset.Available - result.Amount

            elif tx.Type == TransactionType.ClaimTransaction:

                for input in tx.Claims:

                    sc = snapshot.SpentCoins.TryGet(input.PrevHash.ToBytes())
                    if sc and sc.HasIndex(input.PrevIndex):
                        sc.DeleteIndex(input.PrevIndex)
                        snapshot.SpentCoins.GetAndChange(
                            input.PrevHash.ToBytes())

            elif tx.Type == TransactionType.EnrollmentTransaction:

                snapshot.Validators.GetAndChange(
                    tx.PublicKey.ToBytes(),
                    lambda: 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:

                def create_contract_state():
                    return ContractState(tx.Code, tx.NeedStorage, tx.Name,
                                         tx.CodeVersion, tx.Author, tx.Email,
                                         tx.Description)

                snapshot.Contracts.GetAndChange(tx.Code.ScriptHash().ToBytes(),
                                                create_contract_state)

            elif tx.Type == TransactionType.InvocationTransaction:
                return ApplicationEngine.Run(TriggerType.Application, tx,
                                             snapshot.Clone(), tx.Gas, True,
                                             wb)
示例#12
0
    def json_rpc_method_handler(self, method, params):

        if method == "getaccountstate":
            acct = Blockchain.Default().GetAccountState(params[0])
            if acct is None:
                try:
                    acct = AccountState(script_hash=Helper.AddrStrToScriptHash(params[0]))
                except Exception as e:
                    raise JsonRpcError(-2146233033, "One of the identified items was in an invalid format.")

            return acct.ToJson()

        elif method == "getassetstate":
            asset_id = UInt256.ParseString(params[0])
            asset = Blockchain.Default().GetAssetState(asset_id.ToBytes())
            if asset:
                return asset.ToJson()
            raise JsonRpcError(-100, "Unknown asset")

        elif method == "getbestblockhash":
            return '0x%s' % Blockchain.Default().CurrentHeaderHash.decode('utf-8')

        elif method == "getblock":
            # this should work for either str or int
            block = Blockchain.Default().GetBlock(params[0])
            if not block:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_block_output(block, params)

        elif method == "getblockcount":
            return Blockchain.Default().Height + 1

        elif method == "getblockhash":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return '0x%s' % Blockchain.Default().GetBlockHash(height).decode('utf-8')
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getblocksysfee":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return Blockchain.Default().GetSysFeeAmountByHeight(height)
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getconnectioncount":
            return len(NodeLeader.Instance().Peers)

        elif method == "getcontractstate":
            script_hash = UInt160.ParseString(params[0])
            contract = Blockchain.Default().GetContract(script_hash.ToBytes())
            if contract is None:
                raise JsonRpcError(-100, "Unknown contract")
            return contract.ToJson()

        elif method == "getrawmempool":
            return list(map(lambda hash: "0x%s" % hash.decode('utf-8'), NodeLeader.Instance().MemPool.keys()))

        elif method == "getversion":
            return {
                "port": self.port,
                "nonce": NodeLeader.Instance().NodeId,
                "useragent": settings.VERSION_NAME
            }

        elif method == "getrawtransaction":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")
            return self.get_tx_output(tx, height, params)

        elif method == "getLastBlog":

            if len(params) > 0:
                height = params[0]
            else:
                height = Blockchain.Default().Height + 1
            data = self.get_blog_content(height, "")
            return data;
        elif method == "getLastBlogByTag":

            if len(params) > 1:
                height = params[1]
                tag = params[0]
            elif len(params) > 0:
                tag = params[0]
                height = Blockchain.Default().Height + 1
            else:
                raise JsonRpcError(-100, "no enough param")
            data = self.get_blog_content(height, tag)
            return data;
        elif method == "getLastBlogBySender":

            if len(params) > 1:
                height = params[1]
                sender = params[0]
            elif len(params) > 0:
                sender = params[0]
                height = Blockchain.Default().Height + 1
            else:
                raise JsonRpcError(-100, "no enough param")
            data = self.get_blog_content(height, "", sender)
            return data;
        elif method == "getBlogContent":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")

            for attr in tx.Attributes:
                item = attr.ToJson;
                if item['usage'] == 240:
                    item['content'] = binascii.a2b_hex(item['data']).decode("utf8")
                    return item;
            raise JsonRpcError(-100, "no blog content")


        elif method == "getstorage":
            script_hash = UInt160.ParseString(params[0])
            key = binascii.unhexlify(params[1].encode('utf-8'))
            storage_key = StorageKey(script_hash=script_hash, key=key)
            storage_item = Blockchain.Default().GetStorageItem(storage_key)
            if storage_item:
                return storage_item.Value.hex()
            return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "createAddress":

            private_key = bytes(Random.get_random_bytes(32))
            key = KeyPair(priv_key=private_key)
            self.wallet._keys[key.PublicKeyHash.ToBytes()] = key
            self.wallet.OnCreateAccount(key)
            contract = WalletContract.CreateSignatureContract(key.PublicKey)
            self.wallet.AddContract(contract)
            if key :
                result = {'privateKey': key.Export(),'address':contract.Address}
                return result;
            else:
                return None
        elif method == "invoke":
            shash = UInt160.ParseString(params[0])
            contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
            return self.get_invoke_result(sb.ToArray())
        # elif method == "sendBlog":
        #     shash = UInt160.ParseString(params[0])
        #     contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
        #     sb = ScriptBuilder()
        #     sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
        #     script = sb.ToArray();
        #     tx = ContractTransaction()
        #     tx.inputs = []
        #     tx.outputs = []
        #     attribute = TransactionAttribute(240, params[2].encode('utf-8'))
        #     standard_contract = self.wallet.GetStandardAddress()
        #     data = standard_contract.Data
        #     tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script,
        #                                           data=data)]
        #
        #     tx.Attributes.append(attribute)
        #     tx.Version = 1
        #     tx.scripts = []
        #     BC = GetBlockchain()
        #     contract = BC.GetContract(params[0])
        #     output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash,
        #                                Value=Fixed8.FromDecimal(float(1)),
        #                                script_hash=contract.Code.ScriptHash(),
        #                                )
        #     tx.outputs.append(output)
        #     logger.info("output %s" % output.ToJson(0))
        #     tx.Script = binascii.unhexlify(script)
        #     print("percentage %s %s" % (self.wallet.WalletHeight, Blockchain.Default().Height))
        #     scripthash_from = None
        #     if not self.wallet.IsSynced:
        #         raise JsonRpcError.invalidRequest("wallet not synced")
        #     private_key = None
        #     if len(params) > 3:
        #         from_address = params[3]
        #         if from_address is not None:
        #             scripthash_from = lookup_addr_str(self.wallet, from_address)
        #     if len(params) > 4:
        #         private_key = params[4]
        #     wallet_tx = SendBlog(self.wallet, tx, from_addr=scripthash_from, privatekey=private_key)
        #     if wallet_tx != False:
        #         return wallet_tx.ToJson();
        #     self.wallet.Rebuild()
        #     raise JsonRpcError.invalidRequest("Field 'no enough asset")
        elif method == 'postblog':
            try:

                if len(params) > 3:
                    from_address = params[3]
                assetId =Blockchain.SystemShare().Hash

                if len(params) > 4:
                    private_key = params[4]

                if assetId is None:
                    print("Asset id not found")
                    return False

                contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
                sb = ScriptBuilder()
                sb.EmitAppCallWithJsonArgs(UInt160.ParseString(params[0]), contract_parameters)
                script = sb.ToArray();

                scripthash_from = None

                if from_address is not None:
                    scripthash_from = lookup_addr_str(self.wallet, from_address)

                # f8amount = Fixed8.TryParse(0, require_positive=True)
                # if f8amount is None:
                #     print("invalid amount format")
                #     return False
                #
                # if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(
                #         assetId.ToBytes()).Precision) != 0:
                #     print("incorrect amount precision")
                #     return False
                #
                fee = Fixed8.Zero()
                #
                # output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=contract.Code.ScriptHash())
                tx = InvocationTransaction()

                ttx = self.wallet.MakeTransaction(tx=tx,
                                             change_address=None,
                                             fee=fee,
                                             from_addr=scripthash_from)

                if ttx is None:
                    print("insufficient funds")
                    return False
                standard_contract = self.wallet.GetStandardAddress()
                if scripthash_from is not None:
                    signer_contract = self.wallet.GetContract(scripthash_from)
                else:
                    signer_contract = self.wallet.GetContract(standard_contract)

                if not signer_contract.IsMultiSigContract:
                    data = scripthash_from.Data
                    print(data)
                    tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                                          data=data),TransactionAttribute(usage=TransactionAttributeUsage.Remark1,
                                                          data=from_address.encode('utf-8'))]

                # insert any additional user specified tx attributes
                tx.Attributes.append(TransactionAttribute(240, params[2].encode('utf-8')))
                tx.Script = binascii.unhexlify(script)

                context = ContractParametersContext(tx, isMultiSig=signer_contract.IsMultiSigContract)
                if private_key is not None:
                    prikey = KeyPair.PrivateKeyFromWIF(private_key)
                    kp = KeyPair(prikey)
                self.wallet.Sign(context,kp)
                attributes = [attr.ToJson() for attr in tx.Attributes]
                print("attributes %s" %attributes)
                if context.Completed:

                    tx.scripts = context.GetScripts()

                    #            print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4))

                    relayed = NodeLeader.Instance().Relay(tx)

                    if relayed:
                        self.wallet.SaveTransaction(tx)

                        print("Relayed Tx: %s " % tx.Hash.ToString())
                        return tx.ToJson()
                    else:

                        print("Could not relay tx %s " % tx.Hash.ToString())

                else:
                    print("Transaction initiated, but the signature is incomplete")
                    print(json.dumps(context.ToJson(), separators=(',', ':')))
                    return False

            except Exception as e:
                print("could not send: %s " % e)

            return False
        elif method == "invokefunction":
            contract_parameters = []
            if len(params) > 2:
                contract_parameters = [ContractParameter.FromJson(p).ToVM() for p in params[2]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithOperationAndArgs(UInt160.ParseString(params[0]), params[1], contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokescript":
            script = params[0].encode('utf-8')
            return self.get_invoke_result(script)

        elif method == "sendrawtransaction":
            tx_script = binascii.unhexlify(params[0].encode('utf-8'))
            transaction = Transaction.DeserializeFromBufer(tx_script)
            result = NodeLeader.Instance().Relay(transaction)
            return result

        elif method == "submitblock":
            raise NotImplementedError()

        elif method == "validateaddress":
            return self.validateaddress(params)

        elif method == "getpeers":
            raise NotImplementedError()

        raise JsonRpcError.methodNotFound()
示例#13
0
    def json_rpc_method_handler(self, method, params):

        if method == "getaccountstate":
            acct = Blockchain.Default().GetAccountState(params[0])
            if acct is None:
                try:
                    acct = AccountState(script_hash=Helper.AddrStrToScriptHash(params[0]))
                except Exception as e:
                    raise JsonRpcError(-2146233033, "One of the identified items was in an invalid format.")

            return acct.ToJson()

        elif method == "getassetstate":
            asset_str = params[0]
            if asset_str.lower() == 'neo':
                assetId = Blockchain.Default().SystemShare().Hash
            elif asset_str.lower() == 'gas':
                assetId = Blockchain.Default().SystemCoin().Hash
            else:
                assetId = UInt256.ParseString(params[0])
            asset = Blockchain.Default().GetAssetState(assetId.ToBytes())
            if asset:
                return asset.ToJson()
            raise JsonRpcError(-100, "Unknown asset")

        elif method == "getbestblockhash":
            return '0x%s' % Blockchain.Default().CurrentHeaderHash.decode('utf-8')

        elif method == "getblock":
            # this should work for either str or int
            block = Blockchain.Default().GetBlock(params[0])
            if not block:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_block_output(block, params)

        elif method == "getblockcount":
            return Blockchain.Default().Height + 1

        elif method == "getblockhash":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return '0x%s' % Blockchain.Default().GetBlockHash(height).decode('utf-8')
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getblocksysfee":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return Blockchain.Default().GetSysFeeAmountByHeight(height)
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getconnectioncount":
            return len(self.nodemgr.nodes)

        elif method == "getcontractstate":
            script_hash = UInt160.ParseString(params[0])
            contract = Blockchain.Default().GetContract(script_hash.ToBytes())
            if contract is None:
                raise JsonRpcError(-100, "Unknown contract")
            return contract.ToJson()

        elif method == "getrawmempool":
            raise JsonRpcError(-100, "Not supported")
            # return list(map(lambda hash: f"{hash.To0xString()}", self.nodemgr.mempool.pool.keys()))

        elif method == "getversion":
            return {
                "port": self.port,
                "nonce": self.nodemgr.id,
                "useragent": settings.VERSION_NAME
            }

        elif method == "getrawtransaction":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")
            return self.get_tx_output(tx, height, params)

        elif method == "getstorage":
            script_hash = UInt160.ParseString(params[0])
            key = binascii.unhexlify(params[1].encode('utf-8'))
            storage_key = StorageKey(script_hash=script_hash, key=key)
            storage_item = Blockchain.Default().GetStorageItem(storage_key)
            if storage_item:
                return storage_item.Value.hex()
            return None

        elif method == "gettransactionheight":
            try:
                hash = UInt256.ParseString(params[0])
            except Exception:
                # throws exception, not anything more specific
                raise JsonRpcError(-100, "Unknown transaction")

            tx, height = Blockchain.Default().GetTransaction(hash)
            if tx:
                return height
            else:
                raise JsonRpcError(-100, "Unknown transaction")

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "invoke":
            shash = UInt160.ParseString(params[0])
            contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokefunction":
            contract_parameters = []
            if len(params) > 2:
                contract_parameters = [ContractParameter.FromJson(p).ToVM() for p in params[2]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithOperationAndArgs(UInt160.ParseString(params[0]), params[1], contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokescript":
            script = params[0].encode('utf-8')
            return self.get_invoke_result(script)

        elif method == "sendrawtransaction":
            tx_script = binascii.unhexlify(params[0].encode('utf-8'))
            transaction = Transaction.DeserializeFromBufer(tx_script)
            # TODO: relay blocks, change to await in the future
            result = self.nodemgr.relay(transaction)
            return result

        elif method == "validateaddress":
            return self.validateaddress(params)

        elif method == "getpeers":
            return self.get_peers()

        elif method == "getbalance":
            if self.wallet:
                return self.get_balance(params)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getwalletheight":
            if self.wallet:
                return self.wallet.WalletHeight
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "listaddress":
            if self.wallet:
                return self.list_address()
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getnewaddress":
            if self.wallet:
                keys = self.wallet.CreateKey()
                account = Account.get(
                    PublicKeyHash=keys.PublicKeyHash.ToBytes()
                )
                return account.contract_set[0].Address.ToString()
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "sendtoaddress":
            if self.wallet:
                contract_tx, fee = self.parse_send_to_address_params(params)
                return self.process_transaction(contract_tx=contract_tx, fee=fee)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "sendfrom":
            if self.wallet:
                contract_tx, address_from, fee, change_addr = self.parse_send_from_params(params)
                return self.process_transaction(contract_tx=contract_tx, fee=fee, address_from=address_from, change_addr=change_addr)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "sendmany":
            if self.wallet:
                contract_tx, fee, change_addr = self.parse_send_many_params(params)
                return self.process_transaction(contract_tx=contract_tx, fee=fee, change_addr=change_addr)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getblockheader":
            # this should work for either str or int
            blockheader = Blockchain.Default().GetHeaderBy(params[0])
            if not blockheader:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_blockheader_output(blockheader, params)

        raise JsonRpcError.methodNotFound()
示例#14
0
    async def Persist(self, block):

        self._persisting_block = block

        snapshot = self._db.createSnapshot()
        snapshot.PersistingBlock = block

        amount_sysfee = self.GetSysFeeAmount(
            block.PrevHash) + (block.TotalFees().value / Fixed8.D)
        amount_sysfee_bytes = struct.pack("<d", amount_sysfee)
        to_dispatch = []

        with self._db.getBatch() as wb:
            wb.put(DBPrefix.DATA_Block + block.Hash.ToBytes(),
                   amount_sysfee_bytes + block.Trim())

            for tx_idx, tx in enumerate(block.Transactions):
                with self._db.getBatch() as tx_wb:
                    tx_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)
                    snapshot.UnspentCoins.Add(tx.Hash.ToBytes(),
                                              unspentcoinstate)

                    # go through all the accounts in the tx outputs
                    for output in tx.outputs:
                        account = snapshot.Accounts.GetAndChange(
                            output.AddressBytes,
                            lambda: 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:

                            snapshot.UnspentCoins.GetAndChange(
                                input.PrevHash.ToBytes()).Items[
                                    input.PrevIndex] |= CoinState.Spent

                            if prevTx.outputs[input.PrevIndex].AssetId.ToBytes(
                            ) == Blockchain.SystemShare().Hash.ToBytes():
                                sc = snapshot.SpentCoins.GetAndChange(
                                    input.PrevHash.ToBytes(),
                                    lambda: SpentCoinState(
                                        input.PrevHash, height, []))
                                sc.Items.append(
                                    SpentCoinItem(input.PrevIndex,
                                                  block.Index))

                            output = prevTx.outputs[input.PrevIndex]
                            acct = snapshot.Accounts.GetAndChange(
                                prevTx.outputs[input.PrevIndex].AddressBytes,
                                lambda: 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)

                        snapshot.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 = snapshot.Assets.GetAndChange(
                                result.AssetId.ToBytes())
                            asset.Available = asset.Available - result.Amount

                    elif tx.Type == TransactionType.ClaimTransaction:
                        for input in tx.Claims:

                            sc = snapshot.SpentCoins.TryGet(
                                input.PrevHash.ToBytes())
                            if sc and sc.HasIndex(input.PrevIndex):
                                sc.DeleteIndex(input.PrevIndex)
                                snapshot.SpentCoins.GetAndChange(
                                    input.PrevHash.ToBytes())

                    elif tx.Type == TransactionType.EnrollmentTransaction:
                        snapshot.Validators.GetAndChange(
                            tx.PublicKey.ToBytes(),
                            lambda: ValidatorState(pub_key=tx.PublicKey))
                    elif tx.Type == TransactionType.StateTransaction:
                        # @TODO Implement persistence for State Descriptors
                        pass

                    elif tx.Type == TransactionType.PublishTransaction:

                        def create_contract_state():
                            return ContractState(tx.Code, tx.NeedStorage,
                                                 tx.Name, tx.CodeVersion,
                                                 tx.Author, tx.Email,
                                                 tx.Description)

                        snapshot.Contracts.GetOrAdd(
                            tx.Code.ScriptHash().ToBytes(),
                            create_contract_state)
                    elif tx.Type == TransactionType.InvocationTransaction:

                        engine = ApplicationEngine(TriggerType.Application, tx,
                                                   snapshot.Clone(), tx.Gas)
                        engine.LoadScript(tx.Script)

                        try:
                            success = engine.Execute()
                            if success:
                                engine._Service.Commit()
                                engine._Service.ExecutionCompleted(
                                    engine, success)
                            else:
                                engine._Service.ExecutionCompleted(
                                    engine, False)

                        except Exception as e:
                            traceback.print_exc()

                        to_dispatch = to_dispatch + engine._Service.events_to_dispatch
                        await asyncio.sleep(0.001)

                    else:
                        if tx.Type != b'\x00' and tx.Type != b'\x80':
                            logger.info("TX Not Found %s " % tx.Type)

            snapshot.Commit()
            snapshot.Dispose()

            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)