示例#1
0
 def Contracts(self):
     if not self._contracts:
         self._contracts = Blockchain.Default().GetStates(DBPrefix.ST_Contract, ContractState)
     return self._contracts
示例#2
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)

            # 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
            self._persisting_block = None

            for event in to_dispatch:
                events.emit(event.event_type, event)
示例#3
0
def TestInvokeContract(wallet,
                       args,
                       withdrawal_tx=None,
                       parse_params=True,
                       from_addr=None,
                       min_fee=DEFAULT_MIN_FEE):

    BC = GetBlockchain()

    contract = BC.GetContract(args[0])

    if contract:

        verbose = False

        if 'verbose' in args:
            descripe_contract(contract)
            verbose = True
            args.remove('verbose')


#
        params = args[1:] if len(args) > 1 else []

        if len(params) > 0 and params[0] == 'describe':
            return

        params, neo_to_attach, gas_to_attach = get_asset_attachments(params)

        params.reverse()

        sb = ScriptBuilder()

        for p in params:

            if parse_params:
                item = parse_param(p, wallet)
            else:
                item = p

            if type(item) is list:
                item.reverse()
                listlength = len(item)
                for listitem in item:
                    sb.push(listitem)
                sb.push(listlength)
                sb.Emit(PACK)
            else:
                sb.push(item)

        sb.EmitAppCall(contract.Code.ScriptHash().Data)

        out = sb.ToArray()

        outputs = []

        if neo_to_attach:

            output = TransactionOutput(
                AssetId=Blockchain.SystemShare().Hash,
                Value=neo_to_attach,
                script_hash=contract.Code.ScriptHash(),
            )
            outputs.append(output)

        if gas_to_attach:

            output = TransactionOutput(AssetId=Blockchain.SystemCoin().Hash,
                                       Value=gas_to_attach,
                                       script_hash=contract.Code.ScriptHash())

            outputs.append(output)

        return test_invoke(out, wallet, outputs, withdrawal_tx, from_addr,
                           min_fee)

    else:

        print("Contract %s not found" % args[0])

    return None, None, None, None
示例#4
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-m",
                        "--mainnet",
                        action="store_true",
                        default=False,
                        help="Use MainNet instead of the default TestNet")
    parser.add_argument("-p",
                        "--privnet",
                        action="store_true",
                        default=False,
                        help="Use PrivNet instead of the default TestNet")
    parser.add_argument("-c",
                        "--config",
                        action="store",
                        help="Use a specific config file")
    parser.add_argument(
        "-t",
        "--set-default-theme",
        dest="theme",
        choices=["dark", "light"],
        help=
        "Set the default theme to be loaded from the config file. Default: 'dark'"
    )
    parser.add_argument(
        '--version',
        action='version',
        version='neo-python v{version}'.format(version=__version__))

    args = parser.parse_args()

    if args.config and (args.mainnet or args.privnet):
        print(
            "Cannot use both --config and --mainnet/--privnet arguments, please use only one."
        )
        exit(1)
    if args.mainnet and args.privnet:
        print("Cannot use both --mainnet and --privnet arguments")
        exit(1)

    # Setup depending on command line arguments. By default, the testnet settings are already loaded.
    if args.config:
        settings.setup(args.config)
    elif args.mainnet:
        settings.setup_mainnet()
    elif args.privnet:
        settings.setup_privnet()

    if args.theme:
        preferences.set_theme(args.theme)

    # Instantiate the blockchain and subscribe to notifications
    blockchain = LevelDBBlockchain(settings.LEVELDB_PATH)
    Blockchain.RegisterBlockchain(blockchain)

    # Start the prompt interface
    cli = PromptInterface()

    # Run
    reactor.suggestThreadPoolSize(15)
    reactor.callInThread(cli.run)
    NodeLeader.Instance().Start()
    reactor.run()
示例#5
0
    async def StartProcol(self):

        message = Message(
            "version",
            VersionPayload(self._local_node._port, self._local_node._nonce,
                           self._local_node.UserAgent))
        result_future = await asyncio.wait_for(self.SendMessageAsync(message),
                                               60.0)
        if not result_future: return

        message_rec = await asyncio.wait_for(
            self.ReceiveMessageAsync(self.HalfMinute), 60.0)

        if message_rec is None: return

        try:
            if message_rec.Command != 'version':
                self.__log.debug("command is not version...., disconnecting")
                self.Disconnect(True)
                return
        except Exception as e:
            print("could not receive message command %s " % e)
            return

        try:
            self.Version = IOHelper.AsSerializableWithType(
                message_rec.Payload,
                "neo.Network.Payloads.VersionPayload.VersionPayload")
            self.__log.debug("CURRENT VERSION START HEIGHT: %s " %
                             self.Version.StartHeight)

        except Exception as e:
            print("exception getting version: %s " % e)
            self.Disconnect(e)
            return

        if self.Version.Nonce != self._local_node._nonce:
            self.__log.debug("unequal nonces: %s %s " %
                             (self.Version.Nonce, self._local_node._nonce))
#            self.Disconnect(True)
#            return

#lock localnode connected peers
#        if (localNode.connectedPeers.Where(p= > p != this).Any(p= > p.RemoteEndpoint.Address.Equals(
#                RemoteEndpoint.Address) & & p.Version?.Nonce == Version.Nonce))
#        {
#            Disconnect(false);
#        return;
#        }

#endlock

        if self.ListenerEndpoint is not None:
            if self.ListenerEndpoint.Port != self.Version.Port:
                self.Disconnect(True)
                return

        elif self.Version.Port > 0:
            self.ListenerEndpoint = IPEndpoint(self.RemoteEndpoint.Address,
                                               self.Version.Port)

        verack = await asyncio.wait_for(
            self.SendMessageAsync(Message("verack")), 60.0)

        if verack is None or verack is False:
            return

        self.__log.debug("VERACK")

        vmessage = await asyncio.wait_for(
            self.ReceiveMessageAsync(self.HalfMinute), 60.0)

        if vmessage is None or vmessage.Command != "verack":
            self.Disconnect(True)
            return

        self.__log.debug(
            "Header height, start height: %s %s" %
            (Blockchain.Default().HeaderHeight(), self.Version.StartHeight))

        if Blockchain.Default().HeaderHeight() < self.Version.StartHeight:
            self.__log.debug(
                "XXXXXXXXXXXX ENCQUING GET HEADERS MESSSSAAGGEGEE %s " %
                Blockchain.Default().CurrentHeaderHash())
            self.EnqueueMessage(
                "getheaders",
                GetBlocksPayload(Blockchain.Default().CurrentHeaderHash()),
                True)

        sendloop = asyncio.run_coroutine_threadsafe(self.StartSendLoop(),
                                                    asyncio.get_event_loop())

        while self._disposed == 0:

            if Blockchain.Default() is not None:

                if len(self._missions) == 0 and Blockchain.Default().Height(
                ) < self.Version.StartHeight:
                    self.__log.debug("GET BLOCKS MESSAGE %s" %
                                     Blockchain.Default().CurrentBlockHash())
                    self.EnqueueMessage(
                        "getblocks",
                        GetBlocksPayload(
                            Blockchain.Default().CurrentBlockHash()), True)

            timeout = self.HalfHour if len(
                self._missions) == 0 else self.OneMinute

            receive_message_future = await asyncio.wait_for(
                self.ReceiveMessageAsync(timeout), 10)

            if not receive_message_future:
                print("no message future!: ")
                break

            try:
                self.OnMessageReceived(receive_message_future)
            except Exception as e:
                print("could not receive message: %s " % e)
                self.Disconnect(True)
                break
示例#6
0
def test_invoke(script, wallet, outputs, withdrawal_tx=None):

    #    print("invoke script %s " % script)

    bc = GetBlockchain()

    sn = bc._db.snapshot()

    accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator,
                              ValidatorState)
    contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

    # if we are using a withdrawal tx, don't recreate the invocation tx
    # also, we don't want to reset the inputs / outputs
    # since those were already calculated
    if withdrawal_tx is not None:
        tx = withdrawal_tx

    else:
        tx = InvocationTransaction()
        tx.outputs = outputs
        tx.inputs = []

    tx.Version = 1
    tx.scripts = []
    tx.Script = binascii.unhexlify(script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    if len(outputs) < 1:
        contract = wallet.GetDefaultContract()
        tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=Crypto.ToScriptHash(
                                     contract.Script).Data)
        ]

    # same as above. we don't want to re-make the transaction if it is a withdrawal tx
    if withdrawal_tx is not None:
        wallet_tx = tx
    else:
        wallet_tx = wallet.MakeTransaction(tx=tx)

    if wallet_tx:

        context = ContractParametersContext(wallet_tx)
        wallet.Sign(context)
        if context.Completed:
            wallet_tx.scripts = context.GetScripts()

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

    engine.LoadScript(wallet_tx.Script, False)

    try:
        # drum roll?
        success = engine.Execute()

        if success:

            service.TestCommit()

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

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed.value = int(consumed.value)

            net_fee = None
            tx_gas = None

            if consumed < Fixed8.FromDecimal(10.0):
                net_fee = Fixed8.FromDecimal(.001)
                tx_gas = Fixed8.Zero()
            else:
                tx_gas = consumed
                net_fee = Fixed8.Zero()

            # set the amount of gas the tx will need
            wallet_tx.Gas = tx_gas
            # reset the wallet outputs
            wallet_tx.outputs = outputs
            wallet_tx.Attributes = []

            return wallet_tx, net_fee, engine.EvaluationStack.Items, engine.ops_processed
        else:
            print("error executing contract.....")
            return None, None, None, None

    except Exception as e:
        print("COULD NOT EXECUTE %s " % e)

    return None, None, None, None
示例#7
0
 def quit(self):
     print('Shutting down.  This may take a bit...')
     self.go_on = False
     Blockchain.Default().Dispose()
     reactor.stop()
     NodeLeader.Instance().Shutdown()
示例#8
0
    def runPrompt(self):

        dbloop = task.LoopingCall(Blockchain.Default().PersistBlocks)
        dbloop.start(.1)

        Blockchain.Default().PersistBlocks()

        self.createWallet()
        self.autoDeploy()

        print("\n")

        # self.withdrawFunds(self.Wallet)
        # self.exit()

        while self.go_on:

            try:
                result = prompt(
                    "neoFund> ",
                    completer=self.get_completer(),
                    history=self.history,
                    get_bottom_toolbar_tokens=self.get_bottom_toolbar,
                    style=self.token_style,
                    refresh_interval=.5)
            except EOFError:
                # Control-D pressed: quit
                return self.quit()
            except KeyboardInterrupt:
                # Control-C pressed: do nothing
                continue
            try:
                command, arguments = self.parse_result(result)

                if command is not None and len(command) > 0:
                    # command = command.lower()
                    print(command)
                    if command == 'quit' or command == 'exit':
                        self.quit()
                    elif command == 'help':
                        self.help()
                    elif command == 'tx':
                        self.show_tx(arguments)
                    elif command == 'wallet':
                        self.show_wallet(arguments)
                    elif command == 'invokeDeploy':
                        self.invokeDeploy()
                    elif command == 'createFund':
                        self.createFund(self.Wallet, test_fund, 'neo',
                                        'withdrawal_SH', 100, 9999)
                    elif command == 'getFundParameter':
                        self.getFundParameter(self.Wallet, test_fund,
                                              'fundBalance')
                    elif command == 'depositFunds':
                        self.depositFunds(self.Wallet,
                                          test_fund,
                                          'neo',
                                          5,
                                          args=arguments)
                    elif command == 'withdrawFunds':
                        self.withdrawFunds(self.Wallet, 1, args=arguments)
                    elif command == 'withdrawRequestFunds':
                        self.withdrawRequestFunds(self.Wallet,
                                                  test_fund,
                                                  1,
                                                  args=arguments)
                    elif command == 'withdrawRequestReset':
                        self.withdrawRequestReset(self.Wallet)
                    elif command == 'importContract':
                        self.importContract()
                    elif command == 'send_test_funds':
                        self.send_test_funds()
                    elif command == 'deleteAddr':
                        DeleteAddress(self, self.Wallet, arguments[0])
                    elif command == 'isRefundActive':
                        self.isRefundActive(test_fund)
                    elif command is None:
                        print('please specify a command')
                    else:
                        print("command %s not found" % command)

            except Exception as e:

                print("could not execute command: %s " % e)
                traceback.print_stack()
                traceback.print_exc()
    def ExecutionCompleted(self, engine, success, error=None):

        height = Blockchain.Default().Height
        tx_hash = None

        if engine.ScriptContainer:
            tx_hash = engine.ScriptContainer.Hash

        if not tx_hash:
            tx_hash = UInt256(data=bytearray(32))

        entry_script = None
        try:
            # get the first script that was executed
            # this is usually the script that sets up the script to be executed
            entry_script = UInt160(data=engine.ExecutedScriptHashes[0])

            # ExecutedScriptHashes[1] will usually be the first contract executed
            if len(engine.ExecutedScriptHashes) > 1:
                entry_script = UInt160(data=engine.ExecutedScriptHashes[1])
        except Exception as e:
            logger.error("Could not get entry script: %s " % e)

        payload = []
        for item in engine.EvaluationStack.Items:
            payload_item = stack_item_to_py(item)
            payload.append(payload_item)

        if success:

            # dispatch all notify events, along with the success of the contract execution
            for notify_event_args in self.notifications:
                self.events_to_dispatch.append(
                    NotifyEvent(SmartContractEvent.RUNTIME_NOTIFY,
                                notify_event_args.State,
                                notify_event_args.ScriptHash, height, tx_hash,
                                success, engine.testMode))

            if engine.Trigger == Application:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.EXECUTION_SUCCESS,
                                       payload, entry_script, height, tx_hash,
                                       success, engine.testMode))
            else:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.VERIFICATION_SUCCESS,
                                       payload, entry_script, height, tx_hash,
                                       success, engine.testMode))

        else:
            if engine.Trigger == Application:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.EXECUTION_FAIL,
                                       [payload, error, engine._VMState],
                                       entry_script, height, tx_hash, success,
                                       engine.testMode))
            else:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.VERIFICATION_FAIL,
                                       [payload, error, engine._VMState],
                                       entry_script, height, tx_hash, success,
                                       engine.testMode))

        self.notifications = []
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)
示例#11
0
 def AskForMoreHeaders(self):
     # self.Log("asking for more headers...")
     get_headers_message = Message(
         "getheaders",
         GetBlocksPayload(hash_start=[BC.Default().CurrentHeaderHash]))
     self.SendSerializedMessage(get_headers_message)
    def setUpClass(cls):

        Blockchain.DeregisterBlockchain()

        super(BlockchainFixtureTestCase, cls).setUpClass()

        # for some reason during testing asyncio.get_event_loop() fails and does not create a new one if needed. This is the workaround
        try:
            loop = asyncio.get_running_loop()
        except RuntimeError:
            loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        nodemgr = NodeManager()
        nodemgr.reset_for_test()

        # setup Blockchain DB
        if not os.path.exists(cls.FIXTURE_FILENAME):
            logger.info(
                "downloading fixture block database from %s. this may take a while"
                % cls.FIXTURE_REMOTE_LOC)

            response = requests.get(cls.FIXTURE_REMOTE_LOC, stream=True)

            response.raise_for_status()
            os.makedirs(os.path.dirname(cls.FIXTURE_FILENAME), exist_ok=True)
            with open(cls.FIXTURE_FILENAME, 'wb+') as handle:
                for block in response.iter_content(1024):
                    handle.write(block)

        try:
            tar = tarfile.open(cls.FIXTURE_FILENAME)
            tar.extractall(path=settings.DATA_DIR_PATH)
            tar.close()
        except Exception as e:
            raise Exception(
                "Could not extract tar file - %s. You may want need to remove the fixtures file %s manually to fix this."
                % (e, cls.FIXTURE_FILENAME))

        if not os.path.exists(cls.leveldb_testpath()):
            raise Exception("Error downloading fixtures at %s" %
                            cls.leveldb_testpath())

        settings.setup_unittest_net()

        cls._blockchain = Blockchain(
            getBlockchainDB(path=cls.leveldb_testpath()),
            skip_version_check=True)

        cls._blockchain.UT = True
        Blockchain.RegisterBlockchain(cls._blockchain)

        # setup Notification DB
        if not os.path.exists(cls.N_FIXTURE_FILENAME):
            logger.info(
                "downloading fixture notification database from %s. this may take a while"
                % cls.N_FIXTURE_REMOTE_LOC)

            response = requests.get(cls.N_FIXTURE_REMOTE_LOC, stream=True)

            response.raise_for_status()
            with open(cls.N_FIXTURE_FILENAME, 'wb+') as handle:
                for block in response.iter_content(1024):
                    handle.write(block)

        try:
            tar = tarfile.open(cls.N_FIXTURE_FILENAME)
            tar.extractall(path=settings.DATA_DIR_PATH)
            tar.close()

        except Exception as e:
            raise Exception(
                "Could not extract tar file - %s. You may want need to remove the fixtures file %s manually to fix this."
                % (e, cls.N_FIXTURE_FILENAME))
        if not os.path.exists(cls.N_NOTIFICATION_DB_NAME):
            raise Exception("Error downloading fixtures at %s" %
                            cls.N_NOTIFICATION_DB_NAME)

        settings.NOTIFICATION_DB_PATH = cls.N_NOTIFICATION_DB_NAME
        ndb = NotificationDB.instance()
        ndb.start()
示例#13
0
async def setup_and_start(loop):
    parser = argparse.ArgumentParser()

    # Network options
    group_network_container = parser.add_argument_group(
        title="Network options")
    group_network = group_network_container.add_mutually_exclusive_group(
        required=True)
    group_network.add_argument("--mainnet",
                               action="store_true",
                               default=False,
                               help="Use MainNet")
    group_network.add_argument("--testnet",
                               action="store_true",
                               default=False,
                               help="Use TestNet")
    group_network.add_argument("--privnet",
                               action="store_true",
                               default=False,
                               help="Use PrivNet")
    group_network.add_argument("--coznet",
                               action="store_true",
                               default=False,
                               help="Use CozNet")
    group_network.add_argument("--config",
                               action="store",
                               help="Use a specific config file")

    # Ports for RPC and REST api
    group_modes = parser.add_argument_group(title="Mode(s)")
    group_modes.add_argument(
        "--port-rpc",
        type=int,
        help="port to use for the json-rpc api (eg. 10332)")
    group_modes.add_argument("--port-rest",
                             type=int,
                             help="port to use for the rest api (eg. 80)")

    # Advanced logging setup
    group_logging = parser.add_argument_group(title="Logging options")
    group_logging.add_argument("--logfile",
                               action="store",
                               type=str,
                               help="Logfile")
    group_logging.add_argument(
        "--syslog",
        action="store_true",
        help=
        "Log to syslog instead of to log file ('user' is the default facility)"
    )
    group_logging.add_argument(
        "--syslog-local",
        action="store",
        type=int,
        choices=range(0, 7 + 1),
        metavar="[0-7]",
        help=
        "Log to a local syslog facility instead of 'user'. Value must be between 0 and 7 (e.g. 0 for 'local0')."
    )
    group_logging.add_argument("--disable-stderr",
                               action="store_true",
                               help="Disable stderr logger")

    # Where to store stuff
    parser.add_argument("--datadir",
                        action="store",
                        help="Absolute path to use for database directories")
    # peers
    parser.add_argument("--minpeers",
                        action="store",
                        type=int,
                        choices=range(1, 10 + 1),
                        metavar="[1-10]",
                        help="Min peers to use for P2P Joining")

    parser.add_argument("--maxpeers",
                        action="store",
                        type=int,
                        choices=range(1, 10 + 1),
                        metavar="[1-10]",
                        help="Max peers to use for P2P Joining")

    # If a wallet should be opened
    parser.add_argument(
        "--wallet",
        action="store",
        help=
        "Open wallet. Will allow you to use methods that require an open wallet"
    )

    # host
    parser.add_argument("--host",
                        action="store",
                        type=str,
                        help="Hostname ( for example 127.0.0.1)",
                        default="0.0.0.0")

    # Now parse
    args = parser.parse_args()
    # print(args)

    if not args.port_rpc and not args.port_rest:
        print("Error: specify at least one of --port-rpc / --port-rest")
        parser.print_help()
        raise SystemExit

    if args.port_rpc == args.port_rest:
        print("Error: --port-rpc and --port-rest cannot be the same")
        parser.print_help()
        raise SystemExit

    if args.logfile and (args.syslog or args.syslog_local):
        print("Error: Cannot only use logfile or syslog at once")
        parser.print_help()
        raise SystemExit

    # Setting the datadir must come before setting the network, else the wrong path is checked at net setup.
    if args.datadir:
        settings.set_data_dir(args.datadir)

    # Network configuration depending on command line arguments. By default, the testnet settings are already loaded.
    if args.config:
        settings.setup(args.config)
    elif args.mainnet:
        settings.setup_mainnet()
    elif args.testnet:
        settings.setup_testnet()
    elif args.privnet:
        settings.setup_privnet()
    elif args.coznet:
        settings.setup_coznet()

    def set_min_peers(num_peers) -> bool:
        try:
            settings.set_min_peers(num_peers)
            print("Minpeers set to ", num_peers)
            return True
        except ValueError:
            print("Please supply a positive integer for minpeers")
            return False

    def set_max_peers(num_peers) -> bool:
        try:
            settings.set_max_peers(num_peers)
            print("Maxpeers set to ", num_peers)
            return True
        except ValueError:
            print("Please supply a positive integer for maxpeers")
            return False

    minpeers = args.minpeers
    maxpeers = args.maxpeers

    if minpeers and maxpeers:
        if minpeers > maxpeers:
            print("minpeers setting cannot be bigger than maxpeers setting")
            return
        if not set_min_peers(minpeers) or not set_max_peers(maxpeers):
            return
    elif minpeers:
        if not set_min_peers(minpeers):
            return
        if minpeers > settings.CONNECTED_PEER_MAX:
            if not set_max_peers(minpeers):
                return
    elif maxpeers:
        if not set_max_peers(maxpeers):
            return
        if maxpeers < settings.CONNECTED_PEER_MIN:
            if not set_min_peers(maxpeers):
                return

    if args.syslog or args.syslog_local is not None:
        # Setup the syslog facility
        if args.syslog_local is not None:
            print("Logging to syslog local%s facility" % args.syslog_local)
            syslog_facility = SysLogHandler.LOG_LOCAL0 + args.syslog_local
        else:
            print("Logging to syslog user facility")
            syslog_facility = SysLogHandler.LOG_USER

        # Setup logzero to only use the syslog handler
        logzero.syslog(facility=syslog_facility)
    else:
        # Setup file logging
        if args.logfile:
            logfile = os.path.abspath(args.logfile)
            if args.disable_stderr:
                print("Logging to logfile: %s" % logfile)
            else:
                print("Logging to stderr and logfile: %s" % logfile)
            logzero.logfile(logfile,
                            maxBytes=LOGFILE_MAX_BYTES,
                            backupCount=LOGFILE_BACKUP_COUNT,
                            disableStderrLogger=args.disable_stderr)

        else:
            print("Logging to stdout and stderr")

    if args.wallet:
        if not os.path.exists(args.wallet):
            print("Wallet file not found")
            return

        passwd = os.environ.get('NEO_PYTHON_JSONRPC_WALLET_PASSWORD', None)
        if not passwd:
            try:
                passwd = prompt("[password]> ", is_password=True)
            except KeyboardInterrupt:
                print("Wallet opening cancelled")
                return

        password_key = to_aes_key(passwd)
        try:
            wallet = UserWallet.Open(args.wallet, password_key)
            asyncio.create_task(
                wallet.sync_wallet(start_block=wallet._current_height))

        except Exception as e:
            print(f"Could not open wallet {e}")
            return
    else:
        wallet = None

    # Disable logging smart contract events
    settings.set_log_smart_contract_events(False)

    # Write a PID file to easily quit the service
    write_pid_file()

    # Instantiate the blockchain and subscribe to notifications
    blockchain = Blockchain(getBlockchainDB())
    Blockchain.RegisterBlockchain(blockchain)

    p2p = NetworkService()
    p2p_task = loop.create_task(p2p.start())
    loop.create_task(custom_background_code())

    NotificationDB.instance().start()

    if args.port_rpc:
        logger.info("Starting json-rpc api server on http://%s:%s" %
                    (args.host, args.port_rpc))
        try:
            rpc_class = load_class_from_path(settings.RPC_SERVER)
        except ValueError as err:
            logger.error(err)
            sys.exit()
        api_server_rpc = rpc_class(wallet=wallet)

        runner = web.AppRunner(api_server_rpc.app)
        await runner.setup()
        site = web.TCPSite(runner, args.host, args.port_rpc)
        await site.start()

    if args.port_rest:
        logger.info("Starting REST api server on http://%s:%s" %
                    (args.host, args.port_rest))
        try:
            rest_api = load_class_from_path(settings.REST_SERVER)
        except ValueError as err:
            logger.error(err)
            sys.exit()
        api_server_rest = rest_api()
        runner = web.AppRunner(api_server_rest.app)
        await runner.setup()
        site = web.TCPSite(runner, args.host, args.port_rpc)
        await site.start()

    return wallet
示例#14
0
 def Storages(self):
     if not self._storages:
         self._storages = Blockchain.Default().GetStates(DBPrefix.ST_Storage, StorageItem)
     return self._storages
示例#15
0
 def NEO(self):
     return Blockchain.Default().SystemShare().Hash
示例#16
0
    def ToJson(self, verbose=False):
        assets = self.GetCoinAssets()
        tokens = list(self._tokens.values())
        assets = assets + tokens

        if Blockchain.Default().Height == 0:
            percent_synced = 0
        else:
            percent_synced = int(100 * self._current_height / Blockchain.Default().Height)

        jsn = {}
        jsn['path'] = self._path

        addresses = []
        has_watch_addr = False
        for addr in Address.select():
            #            print("Script hash %s %s" % (addr.ScriptHash, type(addr.ScriptHash)))
            addr_str = Crypto.ToAddress(UInt160(data=addr.ScriptHash))
            acct = Blockchain.Default().GetAccountState(addr_str)
            token_balances = self.TokenBalancesForAddress(addr_str)
            if acct:
                json = acct.ToJson()
                json['is_watch_only'] = addr.IsWatchOnly
                addresses.append(json)
                if token_balances:
                    json['tokens'] = token_balances
                if addr.IsWatchOnly:
                    has_watch_addr = True
            else:
                addresses.append(addr_str)

        balances = []
        watch_balances = []
        for asset in assets:
            if type(asset) is UInt256:
                bc_asset = Blockchain.Default().GetAssetState(asset.ToBytes())
                total = self.GetBalance(asset).value / Fixed8.D
                watch_total = self.GetBalance(asset, bool(CoinState.WatchOnly)).value / Fixed8.D
                balances.append("[%s]: %s " % (bc_asset.GetName(), total))
                watch_balances.append("[%s]: %s " % (bc_asset.GetName(), watch_total))
            elif type(asset) is WalletNEP5Token:
                balances.append("[%s]: %s " % (asset.symbol, self.GetBalance(asset)))
                watch_balances.append("[%s]: %s " % (asset.symbol, self.GetBalance(asset, True)))

        tokens = []
        for t in self._tokens.values():
            tokens.append(t.ToJson())

        jsn['addresses'] = addresses
        jsn['height'] = self._current_height
        jsn['percent_synced'] = percent_synced
        jsn['synced_balances'] = balances

        if has_watch_addr:
            jsn['synced_watch_only_balances'] = watch_balances

        jsn['public_keys'] = self.PubKeys()
        jsn['tokens'] = tokens

        jsn['claims'] = {
            'available': self.GetAvailableClaimTotal().ToString(),
            'unavailable': self.GetUnavailableBonus().ToString()
        }

        if verbose:
            jsn['coins'] = [coin.ToJson() for coin in self.FindUnspentCoins()]
            jsn['transactions'] = [tx.ToJson() for tx in self.GetTransactions()]
        return jsn
示例#17
0
文件: Wallet.py 项目: lcux/neo-python
    def ProcessNewBlock(self, block):

        added = set()
        changed = set()
        deleted = set()

        self._lock.acquire()
        try:

            for tx in block.Transactions:

                for index, output in enumerate(tx.outputs):

                    state = self.CheckAddressState(output.ScriptHash)

                    if state > 0:
                        key = CoinReference(tx.Hash, index)

                        found = False
                        for coin in self._coins:
                            if coin.CoinRef.Equals(key):
                                coin.State |= CoinState.Confirmed
                                changed.add(coin.CoinRef)
                                found = True
                        if not found:
                            newcoin = Coin.CoinFromRef(
                                key, output, state=CoinState.Confirmed)
                            self._coins.append(newcoin)
                            added.add(newcoin.CoinRef)

                        if state == AddressState.WatchOnly:
                            for coin in self._coins:
                                if coin.CoinRef.Equals(key):
                                    coin.State |= CoinState.WatchOnly
                                    changed.add(coin.CoinRef)

            for tx in block.Transactions:

                for input in tx.inputs:

                    for coin in self._coins:
                        if coin.CoinRef.Equals(input):

                            if coin.TXOutput.AssetId == Blockchain.SystemShare(
                            ).Hash():
                                coin.State |= CoinState.Spent | CoinState.Confirmed
                                changed.add(coin.CoinRef)
                            else:
                                self._coins.remove(coin)
                                deleted.add(coin.CoinRef)

            for claimTx in [
                    tx for tx in block.Transactions
                    if tx.Type == TransactionType.ClaimTransaction
            ]:
                for ref in claimTx.Claims:
                    if ref in self._coins:
                        self._coins.remove(ref)
                        deleted.add(ref)

            self._current_height += 1
            self.OnProcessNewBlock(block, added, changed, deleted)

            if len(added) + len(deleted) + len(changed) > 0:
                self.BalanceChanged()

        except Exception as e:
            print("could not process: %s " % e)
        finally:
            self._lock.release()
                break
            i += 1


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-o", "--output", action="store", help="Filename of wallet that will be created (default: %s)" % WALLET_PATH, default=WALLET_PATH)
    parser.add_argument("-p", "--password", action="store", help="Wallet password (default: %s)" % WALLET_PWD, default=WALLET_PWD)
    parser.add_argument("-t", "--time", action="store", help="Minutes to wait for the MFF to generate GAS (default: %s)" % MINUTES_TO_WAIT_UNTIL_GAS_CLAIM, default=MINUTES_TO_WAIT_UNTIL_GAS_CLAIM)
    parser.add_argument("-w", "--save-privnet-wif", action="store", help="Filename to store created privnet wif key")
    args = parser.parse_args()

    if os.path.isfile(args.output):
        print("Error: Wallet file %s already exists" % args.output)
        exit(1)

    settings.setup_privnet()
    print("Blockchain DB path:", settings.chain_leveldb_path)
    if os.path.exists(settings.chain_leveldb_path):
        print("Warning: Chain database already exists. If this is from a previous private network, you need to delete %s" % settings.chain_leveldb_path)

    blockchain = LevelDBBlockchain(settings.chain_leveldb_path)
    Blockchain.RegisterBlockchain(blockchain)

    reactor.suggestThreadPoolSize(15)
    NodeLeader.Instance().Start()

    pc = PrivnetClaimall(args.output, args.password, args.time, args.save_privnet_wif)
    reactor.callInThread(pc.run)
    reactor.run()
示例#19
0
def test_deploy_and_invoke(deploy_script, invoke_args, wallet):

    bc = GetBlockchain()

    sn = bc._db.snapshot()

    accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator,
                              ValidatorState)
    contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

    dtx = InvocationTransaction()
    dtx.Version = 1
    dtx.outputs = []
    dtx.inputs = []
    dtx.scripts = []
    dtx.Script = binascii.unhexlify(deploy_script)

    dtx = wallet.MakeTransaction(tx=dtx)
    context = ContractParametersContext(dtx)
    wallet.Sign(context)
    dtx.scripts = context.GetScripts()

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    contract = wallet.GetDefaultContract()
    dtx.Attributes = [
        TransactionAttribute(usage=TransactionAttributeUsage.Script,
                             data=Crypto.ToScriptHash(contract.Script))
    ]

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

    engine.LoadScript(dtx.Script, False)

    # first we will execute the test deploy
    # then right after, we execute the test invoke

    try:
        d_success = engine.Execute()

        if d_success:

            items = engine.EvaluationStack.Items

            contract_state = None
            for i in items:
                if type(i) is ContractState:
                    contract_state = i
                    break
                elif type(i) is InteropInterface:
                    item = i.GetInterface('neo.whatever')
                    if type(item) is ContractState:
                        contract_state = item
                        break

            shash = contract_state.Code.ScriptHash()

            invoke_args, neo_to_attach, gas_to_attach = get_asset_attachments(
                invoke_args)

            invoke_args.reverse()

            sb = ScriptBuilder()

            # print("neo, gas %s %s " % (neo_to_attach,gas_to_attach.ToString()))

            sb = ScriptBuilder()

            for p in invoke_args:

                item = parse_param(p)

                if type(item) is list:
                    item.reverse()
                    listlength = len(item)
                    for listitem in item:
                        sb.push(listitem)
                    sb.push(listlength)
                    sb.Emit(PACK)
                else:
                    sb.push(item)

            sb.EmitAppCall(shash.Data)
            out = sb.ToArray()

            outputs = []

            if neo_to_attach:
                output = TransactionOutput(
                    AssetId=Blockchain.SystemShare().Hash,
                    Value=neo_to_attach,
                    script_hash=contract_state.Code.ScriptHash(),
                )
                outputs.append(output)

            if gas_to_attach:
                output = TransactionOutput(
                    AssetId=Blockchain.SystemCoin().Hash,
                    Value=gas_to_attach,
                    script_hash=contract_state.Code.ScriptHash())

                outputs.append(output)

            itx = InvocationTransaction()
            itx.Version = 1
            itx.outputs = outputs
            itx.inputs = []
            itx.scripts = []
            itx.Attributes = []
            itx.Script = binascii.unhexlify(out)

            if len(outputs) < 1:
                contract = wallet.GetDefaultContract()
                itx.Attributes = [
                    TransactionAttribute(
                        usage=TransactionAttributeUsage.Script,
                        data=Crypto.ToScriptHash(contract.Script).Data)
                ]

            itx = wallet.MakeTransaction(tx=itx)
            context = ContractParametersContext(itx)
            wallet.Sign(context)
            itx.scripts = context.GetScripts()

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

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

            engine.LoadScript(itx.Script, False)

            i_success = engine.Execute()

            if i_success:
                service.TestCommit()

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

                consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
                consumed.value = int(consumed.value)

                if consumed < Fixed8.One():
                    consumed = Fixed8.FromDecimal(.001)

                total_ops = engine.ops_processed

                # set the amount of gas the tx will need
                itx.Gas = consumed
                itx.Attributes = []
                result = engine.ResultsForCode(contract_state.Code)
                return itx, result, total_ops
            else:
                print("error executing invoke contract...")

        else:
            print("error executing deploy contract.....")

    except Exception as e:
        print("COULD NOT EXECUTE %s " % e)
        traceback.print_stack()
        traceback.print_exc()

    return None, [], 0
示例#20
0
def main():
    parser = argparse.ArgumentParser()

    group = parser.add_mutually_exclusive_group()
    group.add_argument("-m",
                       "--mainnet",
                       action="store_true",
                       default=False,
                       help="Use MainNet instead of the default TestNet")
    group.add_argument("-p",
                       "--privnet",
                       action="store_true",
                       default=False,
                       help="Use PrivNet instead of the default TestNet")
    group.add_argument(
        "--coznet",
        action="store_true",
        default=False,
        help="Use the CoZ network instead of the default TestNet")
    group.add_argument("-c",
                       "--config",
                       action="store",
                       help="Use a specific config file")

    parser.add_argument(
        "-t",
        "--set-default-theme",
        dest="theme",
        choices=["dark", "light"],
        help=
        "Set the default theme to be loaded from the config file. Default: 'dark'"
    )
    parser.add_argument(
        "--version",
        action="version",
        version="neo-python v{version}".format(version=__version__))

    args = parser.parse_args()

    # Setup depending on command line arguments. By default, the testnet settings are already loaded.
    if args.config:
        settings.setup(args.config)
    elif args.mainnet:
        settings.setup_mainnet()
    elif args.privnet:
        settings.setup_privnet()
    elif args.coznet:
        settings.setup_coznet()

    if args.theme:
        preferences.set_theme(args.theme)

    # Instantiate the blockchain and subscribe to notifications
    blockchain = LevelDBBlockchain(settings.LEVELDB_PATH)
    Blockchain.RegisterBlockchain(blockchain)

    # Try to set up a notification db
    if NotificationDB.instance():
        NotificationDB.instance().start()

    # Start the prompt interface
    cli = PromptInterface()

    # Run things
    reactor.suggestThreadPoolSize(15)
    reactor.callInThread(cli.run)
    NodeLeader.Instance().Start()

    # reactor.run() is blocking, until `quit()` is called which stops the reactor.
    reactor.run()

    # After the reactor is stopped, gracefully shutdown the database.
    NotificationDB.close()
    Blockchain.Default().Dispose()
    NodeLeader.Instance().Shutdown()
示例#21
0
    def run(self):

        dbloop = task.LoopingCall(Blockchain.Default().PersistBlocks)
        dbloop.start(.1)

        Blockchain.Default().PersistBlocks()

        tokens = [(Token.Neo, 'NEO'), (Token.Default, ' cli. Type '),
                  (Token.Command, "'help' "),
                  (Token.Default, 'to get started')]

        print_tokens(tokens, self.token_style)
        print("\n")

        while self.go_on:

            try:
                result = prompt(
                    "neo> ",
                    completer=self.get_completer(),
                    history=self.history,
                    get_bottom_toolbar_tokens=self.get_bottom_toolbar,
                    style=self.token_style,
                    refresh_interval=3)
            except EOFError:
                # Control-D pressed: quit
                return self.quit()
            except KeyboardInterrupt:
                # Control-C pressed: do nothing
                continue

            try:
                command, arguments = self.parse_result(result)

                if command is not None and len(command) > 0:
                    command = command.lower()

                    if command == 'quit' or command == 'exit':
                        self.quit()
                    elif command == 'help':
                        self.help()
                    elif command == 'create':
                        self.do_create(arguments)
                    elif command == 'open':
                        self.do_open(arguments)
                    elif command == 'build':
                        self.do_build(arguments)
                    elif command == 'load_run':
                        self.do_load_n_run(arguments)
                    elif command == 'import':
                        self.do_import(arguments)
                    elif command == 'export':
                        self.do_export(arguments)
                    elif command == 'wallet':
                        self.show_wallet(arguments)
                    elif command == 'send':
                        self.do_send(arguments)
                    elif command == 'sign':
                        self.do_sign(arguments)
                    elif command == 'block':
                        self.show_block(arguments)
                    elif command == 'tx':
                        self.show_tx(arguments)
                    elif command == 'header':
                        self.show_header(arguments)
                    elif command == 'account':
                        self.show_account_state(arguments)
                    elif command == 'asset':
                        self.show_asset_state(arguments)
                    elif command == 'contract':
                        self.show_contract_state(arguments)
                    elif command == 'testinvoke':
                        self.test_invoke_contract(arguments)
                    elif command == 'withdraw_request':
                        self.do_request_withdraw(arguments)
                    elif command == 'withdraw':
                        self.do_withdraw_from(arguments)
                    elif command == 'mem':
                        self.show_mem()
                    elif command == 'nodes' or command == 'node':
                        self.show_nodes()
                    elif command == 'state':
                        self.show_state()
                    elif command == 'config':
                        self.configure(arguments)
                    elif command is None:
                        print('please specify a command')
                    else:
                        print("command %s not found" % command)

            except Exception as e:

                print("could not execute command: %s " % e)
                traceback.print_stack()
                traceback.print_exc()
示例#22
0
    def MakeTransaction(self,
                        tx,
                        change_address=None,
                        fee=Fixed8(0),
                        from_addr=None,
                        use_standard=False,
                        watch_only_val=0,
                        exclude_vin=None,
                        use_vins_for_asset=None):
        """
        This method is used to to calculate the necessary TransactionInputs (CoinReferences) and TransactionOutputs to
        be used when creating a transaction that involves an exchange of system assets, ( NEO, Gas, etc ).

        Args:
            tx (Transaction): The Transaction to be used.
            change_address (UInt160): The address any change for the transaction should be returned to.
            fee (Fixed8): A fee to be attached to the Transaction for network processing purposes.
            from_addr (UInt160): If present, all CoinReferences selected will only come from this address.
            use_standard (bool): If true, only CoinReferences from standard addresses ( not contracts that are smart contracts ) will be used.
            watch_only_val (int): 0 or CoinState.WATCH_ONLY, if present only choose coins that are in a WatchOnly address.
            exclude_vin (list): A list of CoinReferences to NOT use in the making of this tx.
            use_vins_for_asset (list): A list of CoinReferences to use.

        Returns:
            tx: (Transaction) Returns the transaction with oupdated inputs and outputs.
        """

        tx.ResetReferences()
        tx.ResetHashData()

        if not tx.outputs:
            tx.outputs = []
        if not tx.inputs:
            tx.inputs = []

        fee = fee + (tx.SystemFee() * Fixed8.FD())

        #        pdb.set_trace()

        paytotal = {}
        if tx.Type != int.from_bytes(TransactionType.IssueTransaction,
                                     'little'):

            for key, group in groupby(tx.outputs, lambda x: x.AssetId):
                sum = Fixed8(0)
                for item in group:
                    sum = sum + item.Value
                paytotal[key] = sum
        else:
            paytotal = {}

        if fee > Fixed8.Zero():

            if Blockchain.SystemCoin().Hash in paytotal.keys():
                paytotal[Blockchain.SystemCoin().
                         Hash] = paytotal[Blockchain.SystemCoin().Hash] + fee
            else:
                paytotal[Blockchain.SystemCoin().Hash] = fee

        paycoins = {}

        self._vin_exclude = exclude_vin

        for assetId, amount in paytotal.items():

            if use_vins_for_asset is not None and len(
                    use_vins_for_asset
            ) > 0 and use_vins_for_asset[1] == assetId:
                paycoins[assetId] = self.FindCoinsByVins(use_vins_for_asset[0])
            else:
                paycoins[assetId] = self.FindUnspentCoinsByAssetAndTotal(
                    assetId,
                    amount,
                    from_addr=from_addr,
                    use_standard=use_standard,
                    watch_only_val=watch_only_val)

        self._vin_exclude = None

        for key, unspents in paycoins.items():
            if unspents is None:
                logger.error("insufficient funds for asset id: %s " % key)
                return None

        input_sums = {}

        for assetId, unspents in paycoins.items():
            sum = Fixed8(0)
            for coin in unspents:
                sum = sum + coin.Output.Value
            input_sums[assetId] = sum

        if not change_address:
            change_address = self.GetChangeAddress(from_addr=from_addr)

        new_outputs = []

        for assetId, sum in input_sums.items():
            if sum > paytotal[assetId]:
                difference = sum - paytotal[assetId]
                output = TransactionOutput(AssetId=assetId,
                                           Value=difference,
                                           script_hash=change_address)
                new_outputs.append(output)

        inputs = []

        for item in paycoins.values():
            for ref in item:
                inputs.append(ref.Reference)

        tx.inputs = inputs
        tx.outputs = tx.outputs + new_outputs

        return tx
示例#23
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-m",
                        "--mainnet",
                        action="store_true",
                        default=False,
                        help="use MainNet instead of the default TestNet")
    parser.add_argument("-c",
                        "--config",
                        action="store",
                        help="Use a specific config file")

    # Where to store stuff
    parser.add_argument("--datadir",
                        action="store",
                        help="Absolute path to use for database directories")

    parser.add_argument("-i", "--input", help="Where the input file lives")

    parser.add_argument("-t",
                        "--totalblocks",
                        help="Total blocks to import",
                        type=int)

    parser.add_argument("-l",
                        "--logevents",
                        help="Log Smart Contract Events",
                        default=False,
                        action="store_true")

    args = parser.parse_args()

    if args.mainnet and args.config:
        print(
            "Cannot use both --config and --mainnet parameters, please use only one."
        )
        exit(1)

    # Setting the datadir must come before setting the network, else the wrong path is checked at net setup.
    if args.datadir:
        settings.set_data_dir(args.datadir)

    # Setup depending on command line arguments. By default, the testnet settings are already loaded.
    if args.config:
        settings.setup(args.config)
    elif args.mainnet:
        settings.setup_mainnet()

    if args.logevents:
        settings.log_smart_contract_events = True

    if not args.input:
        raise Exception("Please specify an input path")
    file_path = args.input

    with open(file_path, 'rb') as file:

        total_blocks = int.from_bytes(file.read(4), 'little')

        target_dir = os.path.join(settings.DATA_DIR_PATH,
                                  settings.LEVELDB_PATH)
        notif_target_dir = os.path.join(settings.DATA_DIR_PATH,
                                        settings.NOTIFICATION_DB_PATH)

        print("Will import %s blocks to %s" % (total_blocks, target_dir))
        print(
            "This will overwrite any data currently in %s and %s.\nType 'confirm' to continue"
            % (target_dir, notif_target_dir))

        confirm = prompt("[confirm]> ", is_password=False)
        if not confirm == 'confirm':
            print("Cancelled operation")
            return False

        try:
            if os.path.exists(target_dir):
                shutil.rmtree(target_dir)
            if os.path.exists(notif_target_dir):
                shutil.rmtree(notif_target_dir)
        except Exception as e:
            print("Could not remove existing data %s " % e)
            return False

        # Instantiate the blockchain and subscribe to notifications
        blockchain = LevelDBBlockchain(settings.chain_leveldb_path)
        Blockchain.RegisterBlockchain(blockchain)

        chain = Blockchain.Default()

        for index in trange(total_blocks,
                            desc='Importing Blocks',
                            unit=' Block'):

            block_len = int.from_bytes(file.read(4), 'little')

            stream = StreamManager.GetStream(file.read(block_len))
            reader = BinaryReader(stream)
            block = Block()
            block.Deserialize(reader)
            StreamManager.ReleaseStream(stream)

            if block.Index > 0:
                chain.AddBlockDirectly(block)

        file.close()

    print("Imported %s blocks to %s " % (total_blocks, target_dir))
示例#24
0
    def __init__(self, path, passwordKey, create):
        """

        Args:
            path (str): A path indicating where to create or open the wallet.
            passwordKey (str): A password to use in creating or opening the wallet.
            create (bool): Whether to create the wallet or simply open.
        """

        self.AddressVersion = settings.ADDRESS_VERSION
        self._path = path

        if create:
            self._iv = bytes(Random.get_random_bytes(16))
            self._master_key = bytes(Random.get_random_bytes(32))
            self._keys = {}
            self._contracts = {}
            self._coins = {}

            if Blockchain.Default() is None:
                self._indexedDB = LevelDBBlockchain(settings.LEVELDB_PATH)
                Blockchain.RegisterBlockchain(self._indexedDB)
            else:
                self._indexedDB = Blockchain.Default()

            self._current_height = 0

            self.BuildDatabase()

            passwordHash = hashlib.sha256(passwordKey).digest()
            master = AES.new(passwordKey, AES.MODE_CBC, self._iv)
            mk = master.encrypt(self._master_key)
            self.SaveStoredData('PasswordHash', passwordHash)
            self.SaveStoredData('IV', self._iv)
            self.SaveStoredData('MasterKey', mk)
            self.SaveStoredData('MigrationState', '1')

            self.SaveStoredData('Height',
                                self._current_height.to_bytes(4, 'little'))

        else:
            self.BuildDatabase()

            passwordHash = self.LoadStoredData('PasswordHash')
            if passwordHash is None:
                raise Exception("Password hash not found in database")

            hkey = hashlib.sha256(passwordKey).digest()

            if self.LoadStoredData('MigrationState') != '1':
                raise Exception("This wallet is currently vulnerable. Please "
                                "execute the \"reencrypt_wallet.py\" script "
                                "on this wallet before continuing")

            if passwordHash is not None and passwordHash != hkey:
                raise Exception("Incorrect Password")

            self._iv = self.LoadStoredData('IV')
            master_stored = self.LoadStoredData('MasterKey')
            aes = AES.new(passwordKey, AES.MODE_CBC, self._iv)
            self._master_key = aes.decrypt(master_stored)

            self._keys = self.LoadKeyPairs()
            self._contracts = self.LoadContracts()
            self._watch_only = self.LoadWatchOnly()
            self._tokens = self.LoadNEP5Tokens()
            self._coins = self.LoadCoins()
            try:
                h = int(self.LoadStoredData('Height'))
                self._current_height = h
            except Exception as e:
                logger.error("Could not load height data %s " % e)
                self._current_height = 0

            del passwordKey
示例#25
0
    def __init__(self, path):
        super(LevelDBBlockchain, self).__init__()
        self._path = path

        self._header_index = []
        self._header_index.append(
            Blockchain.GenesisBlock().Header.Hash.ToBytes())

        try:
            self._db = plyvel.DB(self._path, create_if_missing=True)
        #            self._db = plyvel.DB(self._path, create_if_missing=True, bloom_filter_bits=16, compression=None)
        except Exception as e:
            logger.info(
                "leveldb unavailable, you may already be running this process: %s "
                % e)
            raise Exception('Leveldb Unavailable')

        version = self._db.get(DBPrefix.SYS_Version)

        if version == self._sysversion:  # or in the future, if version doesn't equal the current version...

            ba = bytearray(self._db.get(DBPrefix.SYS_CurrentBlock, 0))
            self._current_block_height = int.from_bytes(ba[-4:], 'little')

            ba = bytearray(self._db.get(DBPrefix.SYS_CurrentHeader, 0))
            current_header_height = int.from_bytes(ba[-4:], 'little')
            current_header_hash = bytes(ba[:64].decode('utf-8'),
                                        encoding='utf-8')

            #            logger.info("current header hash!! %s " % current_header_hash)
            #            logger.info("current header height, hashes %s %s %s" %(self._current_block_height, self._header_index, current_header_height) )

            hashes = []
            try:
                for key, value in self._db.iterator(
                        prefix=DBPrefix.IX_HeaderHashList):
                    ms = StreamManager.GetStream(value)
                    reader = BinaryReader(ms)
                    hlist = reader.Read2000256List()
                    key = int.from_bytes(key[-4:], 'little')
                    hashes.append({'k': key, 'v': hlist})
                    StreamManager.ReleaseStream(ms)
            #                hashes.append({'index':int.from_bytes(key, 'little'), 'hash':value})

            except Exception as e:
                logger.info("Could not get stored header hash list: %s " % e)

            if len(hashes):
                hashes.sort(key=lambda x: x['k'])
                genstr = Blockchain.GenesisBlock().Hash.ToBytes()
                for hlist in hashes:

                    for hash in hlist['v']:
                        if hash != genstr:
                            self._header_index.append(hash)
                        self._stored_header_count += 1

            if self._stored_header_count == 0:
                headers = []
                for key, value in self._db.iterator(
                        prefix=DBPrefix.DATA_Block):
                    dbhash = bytearray(value)[8:]
                    headers.append(
                        Header.FromTrimmedData(binascii.unhexlify(dbhash), 0))

                headers.sort(key=lambda h: h.Index)
                for h in headers:
                    if h.Index > 0:
                        self._header_index.append(h.Hash.ToBytes())

            elif current_header_height > self._stored_header_count:

                try:
                    hash = current_header_hash
                    targethash = self._header_index[-1]

                    newhashes = []
                    while hash != targethash:
                        header = self.GetHeader(hash)
                        newhashes.insert(0, header)
                        hash = header.PrevHash.ToBytes()

                    self.AddHeaders(newhashes)
                except Exception as e:
                    pass
        else:
            with self._db.write_batch() as wb:
                for key, value in self._db.iterator():
                    wb.delete(key)

            self.Persist(Blockchain.GenesisBlock())
            self._db.put(DBPrefix.SYS_Version, self._sysversion)
示例#26
0
    def ProcessNewBlock(self, block):
        """
        Processes a block on the blockchain.  This should be done in a sequential order, ie block 4 should be
        only processed after block 3.

        Args:
            block: (neo.Core.Block) a block on the blockchain.
        """
        added = set()
        changed = set()
        deleted = set()

        try:
            # go through the list of transactions in the block and enumerate
            # over their outputs
            for tx in block.FullTransactions:

                for index, output in enumerate(tx.outputs):

                    # check to see if the outputs in the tx are in this wallet
                    state = self.CheckAddressState(output.ScriptHash)

                    if state & AddressState.InWallet > 0:

                        # if its in the wallet, check to see if the coin exists yet

                        key = CoinReference(tx.Hash, index)

                        # if it exists, update it, otherwise create a new one
                        if key in self._coins.keys():
                            coin = self._coins[key]
                            coin.State |= CoinState.Confirmed
                            changed.add(coin)
                        else:
                            newcoin = Coin.CoinFromRef(
                                coin_ref=key,
                                tx_output=output,
                                state=CoinState.Confirmed)
                            self._coins[key] = newcoin
                            added.add(newcoin)

                        if state & AddressState.WatchOnly > 0:
                            self._coins[key].State |= CoinState.WatchOnly
                            changed.add(self._coins[key])

            # now iterate over the inputs of the tx and do the same
            for tx in block.FullTransactions:

                for input in tx.inputs:

                    if input in self._coins.keys():
                        if self._coins[
                                input].Output.AssetId == Blockchain.SystemShare(
                                ).Hash:
                            coin = self._coins[input]
                            coin.State |= CoinState.Spent | CoinState.Confirmed
                            changed.add(coin)

                        else:
                            deleted.add(self._coins[input])
                            del self._coins[input]

            for claimTx in [
                    tx for tx in block.Transactions
                    if tx.Type == TransactionType.ClaimTransaction
            ]:

                for ref in claimTx.Claims:
                    if ref in self._coins.keys():
                        deleted.add(self._coins[ref])
                        del self._coins[ref]

            # update the current height of the wallet
            self._current_height += 1

            # in the case that another wallet implementation needs to do something
            # with the coins that have been changed ( ie persist to db ) this
            # method is called
            self.OnProcessNewBlock(block, added, changed, deleted)

            # this is not necessary at the moment, but any outside process
            # that wants to subscribe to the balance changed event could do
            # so from the BalanceChanged method
            if len(added) + len(deleted) + len(changed) > 0:
                self.BalanceChanged()

        except Exception as e:
            traceback.print_stack()
            traceback.print_exc()
            logger.error("could not process %s " % e)
示例#27
0
def do_quit():
    print('Shutting down.')
    Blockchain.Default().Dispose()
    reactor.stop()
    NodeLeader.Instance().Shutdown()
    sys.exit(0)
示例#28
0
 def GAS(self):
     return Blockchain.Default().SystemCoin().Hash
示例#29
0
def test_invoke(script,
                wallet,
                outputs,
                withdrawal_tx=None,
                from_addr=None,
                min_fee=DEFAULT_MIN_FEE):

    # print("invoke script %s " % script)

    if from_addr is not None:
        from_addr = lookup_addr_str(wallet, from_addr)

    bc = GetBlockchain()

    sn = bc._db.snapshot()

    accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator,
                              ValidatorState)
    contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

    # if we are using a withdrawal tx, don't recreate the invocation tx
    # also, we don't want to reset the inputs / outputs
    # since those were already calculated
    if withdrawal_tx is not None:
        tx = withdrawal_tx

    else:
        tx = InvocationTransaction()
        tx.outputs = outputs
        tx.inputs = []

    tx.Version = 1
    tx.scripts = []
    tx.Script = binascii.unhexlify(script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    if len(outputs) < 1:
        contract = wallet.GetDefaultContract()
        tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=Crypto.ToScriptHash(contract.Script,
                                                          unhex=False).Data)
        ]

    # same as above. we don't want to re-make the transaction if it is a withdrawal tx
    if withdrawal_tx is not None:
        wallet_tx = tx
    else:
        wallet_tx = wallet.MakeTransaction(tx=tx, from_addr=from_addr)

    if wallet_tx:

        context = ContractParametersContext(wallet_tx)
        wallet.Sign(context)
        if context.Completed:
            wallet_tx.scripts = context.GetScripts()

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

    engine.LoadScript(wallet_tx.Script, False)

    try:
        # drum roll?
        success = engine.Execute()

        service.ExecutionCompleted(engine, success)

        for event in service.events_to_dispatch:
            events.emit(event.event_type, event)

        if success:

            # this will be removed in favor of neo.EventHub
            if len(service.notifications) > 0:
                for n in service.notifications:
                    Blockchain.Default().OnNotify(n)

            print("Used %s Gas " % engine.GasConsumed().ToString())

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed = consumed.Ceil()

            net_fee = None
            tx_gas = None

            if consumed <= Fixed8.Zero():
                net_fee = min_fee
                tx_gas = Fixed8.Zero()
            else:
                tx_gas = consumed
                net_fee = Fixed8.Zero()

            # set the amount of gas the tx will need
            wallet_tx.Gas = tx_gas
            # reset the wallet outputs
            wallet_tx.outputs = outputs
            wallet_tx.Attributes = []

            return wallet_tx, net_fee, engine.EvaluationStack.Items, engine.ops_processed

        # this allows you to to test invocations that fail
        else:
            wallet_tx.outputs = outputs
            wallet_tx.Attributes = []
            return wallet_tx, min_fee, [], engine.ops_processed

    except Exception as e:
        service.ExecutionCompleted(engine, False, e)


#        print("COULD NOT EXECUTE %s " % e)

    return None, None, None, None
示例#30
0
 def Assets(self):
     if not self._assets:
         self._assets = Blockchain.Default().GetStates(DBPrefix.ST_Asset, AssetState)
     return self._assets