def Run(script, container=None): from neo.Core.Blockchain import Blockchain from neo.SmartContract.StateMachine import StateMachine bc = Blockchain.Default() 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) script_table = CachedScriptTable(contracts) service = StateMachine(accounts, validators, assets, contracts, storages, None) engine = ApplicationEngine(trigger_type=TriggerType.Application, container=container, table=script_table, service=service, gas=Fixed8.Zero(), testMode=True) engine.LoadScript(script, False) try: success = engine.Execute() service.ExecutionCompleted(engine, success) except Exception as e: service.ExecutionCompleted(engine, False, e) return engine
def test_contract_create_block(self): hexdata = binascii.unhexlify(self.contract_create_block) block = Helper.AsSerializableWithType(hexdata, 'neo.Core.Block.Block') self.assertEqual(block.Index, self.contract_block_index) result = Blockchain.Default().Persist(block) self.assertTrue(result) snapshot = Blockchain.Default()._db.snapshot() contracts = DBCollection(Blockchain.Default()._db, snapshot, DBPrefix.ST_Contract, ContractState) contract_added = contracts.TryGet(self.contract_hash) self.assertIsNotNone(contract_added) self.assertEqual(contract_added.HasStorage, False) self.assertEqual(contract_added.Payable, False) self.assertEqual(contract_added.Name, b'test create') self.assertEqual(contract_added.Email, b'*****@*****.**') self.assertEqual( len(Blockchain.Default().SearchContracts("test create")), 1) self.assertEqual( len(Blockchain.Default().SearchContracts("TEST CREate")), 1) self.assertEqual( len(Blockchain.Default().SearchContracts("TEST CREATE!")), 0) code = contract_added.Code self.assertIsNotNone(code) self.assertEqual(code.ReturnType, 255) self.assertEqual(code.ScriptHash().ToBytes(), self.contract_hash) self.assertEqual(code.Script.hex().encode('utf-8'), self.contract_block_script) snapshot.close()
def Runtime_Notify(self, engine): state = engine.EvaluationStack.Pop() payload = ContractParameter.ToParameter(state) args = NotifyEventArgs( engine.ScriptContainer, UInt160(data=engine.CurrentContext.ScriptHash()), payload ) self.notifications.append(args) if settings.emit_notify_events_on_sc_execution_error: # emit Notify events even if the SC execution might fail. tx_hash = engine.ScriptContainer.Hash height = Blockchain.Default().Height + 1 success = None self.events_to_dispatch.append(NotifyEvent(SmartContractEvent.RUNTIME_NOTIFY, payload, args.ScriptHash, height, tx_hash, success, engine.testMode)) return True
def ImportContractAddr(wallet, contract_hash, pubkey_script_hash): """ Args: wallet (Wallet): a UserWallet instance contract_hash (UInt160): hash of the contract to import pubkey_script_hash (UInt160): Returns: neo.SmartContract.Contract.Contract """ contract = Blockchain.Default().GetContract(contract_hash) if not contract or not pubkey_script_hash: print("Could not find contract") return reedeem_script = contract.Code.Script.hex() # there has to be at least 1 param, and the first one needs to be a signature param param_list = bytearray(b'\x00') # if there's more than one param # we set the first parameter to be the signature param if len(contract.Code.ParameterList) > 1: param_list = bytearray(contract.Code.ParameterList) param_list[0] = 0 verification_contract = Contract.Create(reedeem_script, param_list, pubkey_script_hash) address = verification_contract.Address wallet.AddContract(verification_contract) print(f"Added contract address {address} to wallet") return verification_contract
async def AddTransactionLoop(self): # self.new_tx_event.wait() self.__log.debug("Running add transaction loop") while self._disposed == 0: transactions = [] #lock temppool #if len(self._temppool == 0): continue transactions = list(self._temppool) self._temppool = [] #endlock verified = set() #lock mempool transactions = [ tx for tx in transactions if not tx.Hash() in _mempool and not Blockchain.Default().ContainsTransaction(tx.Hash()) ] if len(transactions): mempool_current = [v for k, v in _mempool] for tx in transactions: if tx.Verify(mempool_current + transactions): verified.add(tx) for tx in verified: _mempool[tx.Hash()] = tx self.CheckMemPool() #endlock await self.RelayDirectly(verified) if self.InventoryReceived is not None: [self.InventoryReceived.on_change(tx) for tx in verified]
def show_block(self, args): item = get_arg(args) txarg = get_arg(args, 1) if item is not None: block = Blockchain.Default().GetBlock(item) if block is not None: bjson = json.dumps(block.ToJson(), indent=4) tokens = [(Token.Number, bjson)] print_tokens(tokens, self.token_style) print('\n') if txarg and 'tx' in txarg: # with open("b_1445025.txt",'w') as myfile: # for tx in block.FullTransactions: # myfile.write(json.dumps(tx.ToJson(), indent=4)) for tx in block.FullTransactions: print(json.dumps(tx.ToJson(), indent=4)) else: print("could not locate block %s" % item) else: print("please specify a block")
def format_notifications(self, request, notifications, show_none=False): notif_len = len(notifications) page_len = 500 page = 0 message = '' if b'page' in request.args: try: page = int(request.args[b'page'][0]) except Exception as e: print("could not get page: %s" % e) start = page_len * page end = start + page_len if start > notif_len: message = 'page greater than result length' notifications = notifications[start:end] return json.dumps( { 'current_height': Blockchain.Default().Height, 'message': message, 'total': notif_len, 'results': None if show_none else [n.ToJson() for n in notifications], 'page': page, 'page_len': page_len }, indent=4, sort_keys=True)
def main(): settings.setup('protocol.coz.json') # Setup the blockchain blockchain = LevelDBBlockchain(settings.LEVELDB_PATH) Blockchain.RegisterBlockchain(blockchain) dbloop = task.LoopingCall(Blockchain.Default().PersistBlocks) dbloop.start(.1) NodeLeader.Instance().Start() # Disable smart contract events for external smart contracts settings.set_log_smart_contract_events(False) # Start a thread with custom code d = threading.Thread(target=custom_background_code) d.setDaemon( True ) # daemonizing the thread will kill it when the main thread is quit d.start() # Run all the things (blocking call) logger.info("Everything setup and running. Waiting for events...") reactor.run() logger.info("Shutting down.")
def height_check(self): last_height = 0 neo = self.Wallet.GetBalance(self.Wallet.GetCoinAssets()[0]) gas = self.Wallet.GetBalance(self.Wallet.GetCoinAssets()[1]) while (Blockchain.Default().HeaderHeight - last_height) > 10: print('Updating Height...') last_height = Blockchain.Default().HeaderHeight sleep(5) print('Wallet Height: ', self.Wallet._current_height) print('Blockchain Height: ', Blockchain.Default().Height) print('Header Height: ', Blockchain.Default().HeaderHeight) print('Gas Balance: ', gas) if self.Wallet._current_height <= Blockchain.Default( ).Height - 20 or gas.ToInt() == 0: self.Wallet.Rebuild() while self.Wallet._current_height < Blockchain.Default( ).Height - 2: print('Rebuilding Wallet..') sleep(5)
def test_peer_adding(self): leader = NodeLeader.Instance() Blockchain.Default()._block_cache = {'hello': 1} def mock_call_later(delay, method, *args): method(*args) def mock_connect_tcp(host, port, factory, timeout=120): node = NeoNode() node.endpoint = Endpoint(host, port) leader.AddConnectedPeer(node) return node def mock_disconnect(peer): return True def mock_send_msg(node, message): return True settings.set_max_peers(len(settings.SEED_LIST)) with patch('twisted.internet.reactor.connectTCP', mock_connect_tcp): with patch('twisted.internet.reactor.callLater', mock_call_later): with patch('neo.Network.NeoNode.NeoNode.Disconnect', mock_disconnect): with patch( 'neo.Network.NeoNode.NeoNode.SendSerializedMessage', mock_send_msg): leader.Start() self.assertEqual(len(leader.Peers), len(settings.SEED_LIST)) # now test adding another leader.RemoteNodePeerReceived('hello.com', 1234, 6) # it shouldnt add anything so it doesnt go over max connected peers self.assertEqual(len(leader.Peers), len(settings.SEED_LIST)) # test adding peer peer = NeoNode() peer.endpoint = Endpoint('hellloo.com', 12344) leader.ADDRS.append('hellloo.com:12344') leader.AddConnectedPeer(peer) self.assertEqual(len(leader.Peers), len(settings.SEED_LIST)) # now get a peer peer = leader.Peers[0] leader.RemoveConnectedPeer(peer) self.assertEqual(len(leader.Peers), len(settings.SEED_LIST) - 1) self.assertEqual(len(leader.ADDRS), len(settings.SEED_LIST)) # now test adding another leader.RemoteNodePeerReceived('hello.com', 1234, 6) self.assertEqual(len(leader.Peers), len(settings.SEED_LIST)) # now if we remove all peers, it should restart peers = leader.Peers[:] for peer in peers: leader.RemoveConnectedPeer(peer) # test reset leader.ResetBlockRequestsAndCache() self.assertEqual(Blockchain.Default()._block_cache, {})
def main(): parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group(required=True) group.add_argument("-m", "--mainnet", action="store_true", default=False, help="Use MainNet instead of the default TestNet") group.add_argument("-t", "--testnet", action="store_true", default=False, help="Use TestNett 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("--port-rpc", type=int, help="port to use for the json-rpc api (eg. 10332)") parser.add_argument("--port-rest", type=int, help="port to use for the rest api (eg. 80)") args = parser.parse_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() return if args.port_rpc == args.port_rest: print("Error: --port-rpc and --port-rest cannot be the same") parser.print_help() return # 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.testnet: settings.setup_testnet() elif args.privnet: settings.setup_privnet() elif args.coznet: settings.setup_coznet() # Write a PID file to easily quit the service write_pid_file() # Instantiate the blockchain and subscribe to notifications blockchain = LevelDBBlockchain(settings.LEVELDB_PATH) Blockchain.RegisterBlockchain(blockchain) dbloop = task.LoopingCall(Blockchain.Default().PersistBlocks) dbloop.start(.1) # Disable logging smart contract events settings.set_log_smart_contract_events(False) # Start the notification db instance ndb = NotificationDB.instance() ndb.start() # Start a thread with custom code d = threading.Thread(target=custom_background_code) d.setDaemon(True) # daemonizing the thread will kill it when the main thread is quit d.start() # Run reactor.suggestThreadPoolSize(15) NodeLeader.Instance().Start() host = "0.0.0.0" if args.port_rpc: logger.info("Starting json-rpc api server on http://%s:%s" % (host, args.port_rpc)) api_server_rpc = JsonRpcApi(args.port_rpc) endpoint_rpc = "tcp:port={0}:interface={1}".format(args.port_rpc, host) endpoints.serverFromString(reactor, endpoint_rpc).listen(Site(api_server_rpc.app.resource())) if args.port_rest: logger.info("Starting notification api server on http://%s:%s" % (host, args.port_rest)) api_server_rest = NotificationRestApi() endpoint_rest = "tcp:port={0}:interface={1}".format(args.port_rest, host) endpoints.serverFromString(reactor, endpoint_rest).listen(Site(api_server_rest.app.resource())) app = Klein() app.run(host, 9999)
def run(self): dbloop = task.LoopingCall(Blockchain.Default().PersistBlocks) dbloop.start(.1) Blockchain.Default().PersistBlocks() self.node_leader = NodeLeader.Instance() 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: result = prompt("neo> ", completer=self.completer, history=self.history, get_bottom_toolbar_tokens=self.get_bottom_toolbar, style=self.token_style) 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 == '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 == 'contract': self.show_contract_state(arguments) elif command == 'sc': self.show_spent_coins(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 == 'pause' or command == 'unpause' or command == 'resume': self.toggle_pause() elif command == None: print('please specify a command') else: print("command %s not found" % command) else: pass
class PromptInterface(object): go_on = True completer = WordCompleter([ 'block', 'tx', 'header', 'mem', 'help', 'state', 'node', 'exit', 'quit', 'config', 'db', 'log' ]) commands = [ 'quit', 'help', 'block {index/hash}', 'header {index/hash}', 'tx {hash}', 'mem', 'nodes', 'state', 'config {node, db} int int' 'config log on/off' 'pause', ] token_style = style_from_dict({ Token.Command: '#ff0066', Token.Neo: '#0000ee', Token.Default: '#00ee00', Token.Number: "#ffffff", }) history = InMemoryHistory() start_height = Blockchain.Default().Height start_dt = datetime.datetime.utcnow() node_leader = None paused = False def paused_loop(self): while self.paused: # self.__log.debug("paused...") time.sleep(1) def get_bottom_toolbar(self, cli=None): try: return [(Token.Command, 'Progress: '), (Token.Number, str(Blockchain.Default().Height)), (Token.Neo, '/'), (Token.Number, str(Blockchain.Default().HeaderHeight - 1))] except Exception as e: print("couldnt get toolbar: %s " % e) return [] def quit(self): print('Shutting down. This may take a bit...') self.go_on = False self.paused = False Blockchain.Default().Dispose() reactor.stop() self.node_leader.Shutdown() def help(self): tokens = [] for c in self.commands: tokens.append((Token.Command, "%s\n" % c)) print_tokens(tokens, self.token_style) def toggle_pause(self): if self.paused: self.paused = not self.paused # reactor.run() print("resusiming execution") else: self.paused = not self.paused print('pausing execution!') reactor.callLater(1, self.paused_loop) def show_state(self): height = Blockchain.Default().Height headers = Blockchain.Default().HeaderHeight - 1 diff = height - self.start_height now = datetime.datetime.utcnow() difftime = now - self.start_dt mins = difftime / datetime.timedelta(minutes=1) bpm = 0 if diff > 0 and mins > 0: bpm = diff / mins out = 'Progress: %s / %s\n' % (height, headers) out += 'Block Cache length %s\n' % Blockchain.Default().BlockCacheCount out += 'Blocks since program start %s\n' % diff out += 'Time elapsed %s mins\n' % mins out += 'blocks per min %s \n' % bpm out += "Node Req Part, Max: %s %s\n" % (self.node_leader.BREQPART, self.node_leader.BREQMAX) out += "DB Cache Lim, Miss Lim %s %s\n" % ( Blockchain.Default().CACHELIM, Blockchain.Default().CMISSLIM) tokens = [(Token.Number, out)] print_tokens(tokens, self.token_style) def show_nodes(self): if self.node_leader and len(self.node_leader.Peers): out = '' for peer in self.node_leader.Peers: out += 'Peer %s - IO: %s\n' % (peer.Name(), peer.IOStats()) print_tokens([(Token.Number, out)], self.token_style) else: print('Not connected yet\n') def show_block(self, args): item = self.get_arg(args) txarg = self.get_arg(args, 1) if item is not None: block = Blockchain.Default().GetBlock(item) if block is not None: bjson = json.dumps(block.ToJson(), indent=4) tokens = [(Token.Number, bjson)] print_tokens(tokens, self.token_style) print('\n') if txarg and 'tx' in txarg: for tx in block.Transactions: self.show_tx([tx]) else: print("could not locate block %s" % item) else: print("please specify a block") def show_header(self, args): item = self.get_arg(args) if item is not None: header = Blockchain.Default().GetHeaderBy(item) if header is not None: print(json.dumps(header.ToJson(), indent=4)) else: print("could not locate Header %s \n" % item) else: print("please specify a header") def show_tx(self, args): item = self.get_arg(args) if item is not None: try: tx, height = Blockchain.Default().GetTransaction(item) if height > -1: bjson = json.dumps(tx.ToJson(), indent=4) tokens = [(Token.Command, bjson)] print_tokens(tokens, self.token_style) print('\n') except Exception as e: print("Could not find transaction with id %s " % item) print( "Please specify a tx hash like 'db55b4d97cf99db6826967ef4318c2993852dff3e79ec446103f141c716227f6'" ) else: print("please specify a tx hash") def show_account_state(self, args): item = self.get_arg(args) print("account to show %s " % item) if item is not None: account = Blockchain.Default().GetAccountState( item, print_all_accounts=True) if account is not None: bjson = json.dumps(account.ToJson(), indent=4) tokens = [(Token.Number, bjson)] print_tokens(tokens, self.token_style) print('\n') else: print("account %s not found" % item) else: print("please specify an account address") def show_contract_state(self, args): item = self.get_arg(args) if item is not None: if item.lower() == 'all': contracts = Blockchain.Default().ShowAllContracts() print("contracts: %s " % contracts) else: contract = Blockchain.Default().GetContract(item) if contract is not None: bjson = json.dumps(contract.ToJson(), indent=4) tokens = [(Token.Number, bjson)] print_tokens(tokens, self.token_style) print('\n') else: print("please specify a contract") def show_spent_coins(self, args): item = self.get_arg(args) if item is not None: if item.lower() == 'all': coins = Blockchain.Default().GetAllSpentCoins() print("coins %s " % coins) else: coin = Blockchain.Default().GetSpentCoins(item) if coin is not None: bjson = json.dumps(coin.ToJson(), indent=4) tokens = [(Token.Number, bjson)] print_tokens(tokens, self.token_style) print("\n") else: print("please specify a tx hash") def show_mem(self): total = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss totalmb = total / 1000000 out = "Total: %s MB\n" % totalmb out += "total buffers %s\n" % StreamManager.TotalBuffers() print_tokens([(Token.Number, out)], self.token_style) def configure(self, args): what = self.get_arg(args) if what == 'node': c1 = self.get_arg(args, 1, convert_to_int=True) c2 = self.get_arg(args, 2, convert_to_int=True) if not c1: print("please provide settings. arguments must be integers") if c1 is not None and c1 > 1: if c1 > 200: c1 = 200 print("Node request part must be less than 201") self.node_leader.BREQPART = c1 print("Set Node Request Part to %s " % c1) if c2 is not None and c2 >= self.node_leader.BREQPART: self.node_leader.BREQMAX = c2 print("Set Node Request Max to %s " % c2) self.show_state() elif what == 'db': c1 = self.get_arg(args, 1, convert_to_int=True) c2 = self.get_arg(args, 2, convert_to_int=True) if c1 is not None and c1 > 1: Blockchain.Default().CACHELIM = c1 print("Set DB Cache Limit to %s " % c1) if c2 is not None and c2 >= self.node_leader.BREQPART: Blockchain.Default().CMISSLIM = c2 print("Set DB Cache Miss Limit %s " % c2) self.show_state() elif what == 'log' or what == 'logs': c1 = self.get_arg(args, 1).lower() if c1 is not None: if c1 == 'on' or c1 == '1': print("turning on logging") logger = logging.getLogger() logger.setLevel(logging.DEBUG) if c1 == 'off' or c1 == '0': print("turning off logging") logger = logging.getLogger() logger.setLevel(logging.ERROR) else: print("cannot configure log. Please specify on or off") else: print("cannot configure %s " % what) print( "Try 'config node 100 1000' or config db 1000 4' or config log on/off" ) def get_arg(self, arguments, index=0, convert_to_int=False): try: arg = arguments[index] if convert_to_int: return int(arg) return arg except Exception as e: pass return None def parse_result(self, result): if len(result): commandParts = [s for s in result.split()] return commandParts[0], commandParts[1:] return None, None def run(self): dbloop = task.LoopingCall(Blockchain.Default().PersistBlocks) dbloop.start(.1) Blockchain.Default().PersistBlocks() self.node_leader = NodeLeader.Instance() 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: result = prompt("neo> ", completer=self.completer, history=self.history, get_bottom_toolbar_tokens=self.get_bottom_toolbar, style=self.token_style) 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 == '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 == 'contract': self.show_contract_state(arguments) elif command == 'sc': self.show_spent_coins(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 == 'pause' or command == 'unpause' or command == 'resume': self.toggle_pause() elif command == None: print('please specify a command') else: print("command %s not found" % command) else: pass
def construct_send_tx(wallet, arguments): from_address = arguments['from'] to_send = arguments['asset'] address_to = arguments['to'] amount = arguments['amount'] user_tx_attributes = arguments.get('attrs', []) assetId = get_asset_id(wallet, to_send) if assetId is None: raise Exception("Asset id not found") scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: raise Exception("invalid address") scripthash_from = None if from_address is not None: scripthash_from = lookup_addr_str(wallet, from_address) if type(assetId) is NEP5Token: raise Exception("cannot transfer token in this version") f8amount = Fixed8.TryParse(amount, require_positive=True) if f8amount is None: raise Exception("invalid amount format") if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0: raise Exception("incorrect amount precision") fee = Fixed8.Zero() output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) tx = ContractTransaction(outputs=[output]) ttx = wallet.MakeTransaction(tx=tx, fee=fee, from_addr=scripthash_from) if ttx is None: raise Exception("no funds") standard_contract = wallet.GetStandardAddress() if scripthash_from is not None: signer_contract = wallet.GetContract(scripthash_from) else: signer_contract = wallet.GetContract(standard_contract) if not signer_contract.IsMultiSigContract: data = standard_contract.Data tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=data)] # insert any additional user specified tx attributes tx.Attributes = tx.Attributes + user_tx_attributes context = ContractParametersContext(tx, isMultiSig=signer_contract.IsMultiSigContract) logger.info(context.ToJson()) logger.info('*'*60) logger.info(tx.ToJson()) # import pdb # pdb.set_trace() ms = StreamManager.GetStream() writer = BinaryWriter(ms) tx.Serialize(writer) ms.flush() binary_tx = ms.ToArray() print(tx) return {'context': context.ToJson(), 'tx': binary_tx.decode()}
def construct_deploy_tx(wallet, params): params = params[0] from_addr = params['from_addr'] # load_smart_contract contract_params = bytearray(binascii.unhexlify(params['contract_params'])) return_type = bytearray(binascii.unhexlify(params['return_type'])) contract_properties = 0 if params.get('needs_storage', True): contract_properties += ContractPropertyState.HasStorage if params.get('needs_dynamic_invoke', False): contract_properties += ContractPropertyState.HasDynamicInvoke script = binascii.unhexlify(params['bin']) function_code = FunctionCode( script = script, param_list = contract_params, return_type = return_type, contract_properties = contract_properties, ) if Blockchain.Default().GetContract(function_code.ScriptHash().To0xString()): raise Exception('contract already exists') # GatherContractDetails details = params['details'] name = details['name'] version = details['version'] author = details['author'] email = details['email'] description = details['description'] contract_script = generate_deploy_script( function_code.Script, name, version, author, email, description, function_code.ContractProperties, function_code.ReturnType, function_code.ParameterList, ) # test_invoke bc = GetBlockchain() sn = bc._db.snapshot() accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState) assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState) validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState) contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState) storages = DBCollection(bc._db, DBPrefix.ST_Storage, StorageItem) tx = InvocationTransaction() tx.outputs = [] tx.inputs = [] tx.Version = 1 tx.scripts = [] tx.Script = binascii.unhexlify(contract_script) script_table = CachedScriptTable(contracts) service = StateMachine(accounts, validators, assets, contracts, storages, None) contract = wallet.GetDefaultContract() tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=Crypto.ToScriptHash(contract.Script, unhex=False).Data)] tx = wallet.MakeTransaction(tx=tx) engine = ApplicationEngine( trigger_type=TriggerType.Application, container=tx, table=script_table, service=service, gas=tx.Gas, testMode=True ) engine.LoadScript(tx.Script, False) success = engine.Execute() if not success: raise Exception('exec failed') service.ExecutionCompleted(engine, success) consumed = engine.GasConsumed() - Fixed8.FromDecimal(10) consumed = consumed.Ceil() net_fee = None tx_gas = None if consumed <= Fixed8.Zero(): net_fee = Fixed8.FromDecimal(.0001) tx_gas = Fixed8.Zero() else: tx_gas = consumed net_fee = Fixed8.Zero() tx.Gas = tx_gas tx.outputs = [] tx.Attributes = [] # InvokeContract from_addr = lookup_addr_str(wallet, from_addr) tx = wallet.MakeTransaction(tx=tx, fee=net_fee, use_standard=True, from_addr=from_addr) if tx is None: raise Exception("no gas") context = ContractParametersContext(tx) ms = StreamManager.GetStream() writer = BinaryWriter(ms) tx.Serialize(writer) ms.flush() binary_tx = ms.ToArray() return {'context': context.ToJson(), 'tx': binary_tx.decode(), 'hash': function_code.ScriptHash().To0xString()}
def Asset_Create(self, engine): tx = engine.ScriptContainer asset_type = int(engine.EvaluationStack.Pop().GetBigInteger()) if asset_type not in AssetType.AllTypes() or \ asset_type == AssetType.CreditFlag or \ asset_type == AssetType.DutyFlag or \ asset_type == AssetType.GoverningToken or \ asset_type == AssetType.UtilityToken: return False if len(engine.EvaluationStack.Peek().GetByteArray()) > 1024: return False name = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8') amount = Fixed8(engine.EvaluationStack.Pop().GetBigInteger()) if amount == Fixed8.Zero() or amount < Fixed8.NegativeSatoshi(): return False if asset_type == AssetType.Invoice and amount != Fixed8.NegativeSatoshi( ): return False precision = int(engine.EvaluationStack.Pop().GetBigInteger()) if precision > 8: return False if asset_type == AssetType.Share and precision != 0: return False if amount != Fixed8.NegativeSatoshi() and amount.value % pow( 10, 8 - precision) != 0: return False ownerData = engine.EvaluationStack.Pop().GetByteArray() owner = ECDSA.decode_secp256r1(ownerData, unhex=False).G if owner.IsInfinity: return False if not self.CheckWitnessPubkey(engine, owner): logger.error("check witness false...") return False admin = UInt160(data=engine.EvaluationStack.Pop().GetByteArray()) issuer = UInt160(data=engine.EvaluationStack.Pop().GetByteArray()) new_asset = AssetState(asset_id=tx.Hash, asset_type=asset_type, name=name, amount=amount, available=Fixed8.Zero(), precision=precision, fee_mode=0, fee=Fixed8.Zero(), fee_addr=UInt160(), owner=owner, admin=admin, issuer=issuer, expiration=Blockchain.Default().Height + 1 + 2000000, is_frozen=False) asset = self._assets.GetOrAdd(tx.Hash.ToBytes(), new_asset) # print("*****************************************************") # print("CREATED ASSET %s " % tx.Hash.ToBytes()) # print("*****************************************************") engine.EvaluationStack.PushT(StackItem.FromInterface(asset)) return True
def process_transaction(wallet, contract_tx, scripthash_from=None, scripthash_change=None, fee=None, owners=None, user_tx_attributes=None): try: tx = wallet.MakeTransaction(tx=contract_tx, change_address=scripthash_change, fee=fee, from_addr=scripthash_from) except ValueError: print( "Insufficient funds. No unspent outputs available for building the transaction.\n" "If you are trying to sent multiple transactions in 1 block, then make sure you have enough 'vouts'\n." "Use `wallet unspent` and `wallet address split`, or wait until the first transaction is processed before sending another." ) return except TXFeeError as e: print(e) return if tx is None: logger.debug("insufficient funds") return try: print("Validate your transaction details") print("-" * 33) input_coinref = wallet.FindCoinsByVins(tx.inputs)[0] source_addr = input_coinref.Address for order in tx.outputs: dest_addr = order.Address value = order.Value.ToString() # fixed8 if order.AssetId == Blockchain.Default().SystemShare().Hash: asset_name = 'NEO' else: asset_name = 'GAS' if source_addr != dest_addr: print( f"Sending {value} {asset_name} from {source_addr} to {dest_addr}" ) else: print( f"Returning {value} {asset_name} as change to {dest_addr}") print(" ") print("Enter your password to send to the network") try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Transaction cancelled") return if not wallet.ValidatePassword(passwd): print("Incorrect password") return standard_contract = wallet.GetStandardAddress() if scripthash_from is not None: signer_contract = wallet.GetContract(scripthash_from) else: signer_contract = wallet.GetContract(standard_contract) if not signer_contract.IsMultiSigContract and owners is None: data = standard_contract.Data tx.Attributes = [ TransactionAttribute(usage=TransactionAttributeUsage.Script, data=data) ] # insert any additional user specified tx attributes tx.Attributes = tx.Attributes + user_tx_attributes if owners: owners = list(owners) for owner in owners: tx.Attributes.append( TransactionAttribute( usage=TransactionAttributeUsage.Script, data=owner)) context = ContractParametersContext( tx, isMultiSig=signer_contract.IsMultiSigContract) wallet.Sign(context) if owners: owners = list(owners) gather_signatures(context, tx, owners) if context.Completed: tx.scripts = context.GetScripts() relayed = NodeLeader.Instance().Relay(tx) if relayed: wallet.SaveTransaction(tx) print("Relayed Tx: %s " % tx.Hash.ToString()) return tx else: print("Could not relay tx %s " % tx.Hash.ToString()) else: print( "Transaction initiated, but the signature is incomplete. Use the `sign` command with the information below to complete signing." ) print(json.dumps(context.ToJson(), separators=(',', ':'))) return except Exception as e: print("Could not send: %s " % e) traceback.print_stack() traceback.print_exc() return
def run(self): dbloop = task.LoopingCall(Blockchain.Default().PersistBlocks) dbloop.start(.1) Blockchain.Default().PersistBlocks() while Blockchain.Default().Height < 2: print("Waiting for wallet to sync...") time.sleep(1) print("Creating Wallet...") self.wallet = UserWallet.Create(path=self.wallet_fn, password=self.wallet_pwd) self.wallet.ProcessBlocks() # Extract infos from wallet contract = self.wallet.GetDefaultContract() key = self.wallet.GetKey(contract.PublicKeyHash) address = key.GetAddress() wif = key.Export() print("- Address:", address) print("- WIF key:", wif) self.wallet = None # Claim initial NEO self.claim_initial_neo(address) # Open wallet again self.wallet = UserWallet.Open(self.wallet_fn, self.wallet_pwd) self._walletdb_loop = task.LoopingCall(self.wallet.ProcessBlocks) self._walletdb_loop.start(1) print("\nWait %s min before claiming GAS." % self.min_wait) time.sleep(60 * self.min_wait) print("\nSending NEO to own wallet...") tx = construct_and_send(None, self.wallet, ["neo", address, "100000000"], prompt_password=False) if not tx: print("Something went wrong, no tx.") return # Wait until transaction is on blockchain self.wait_for_tx(tx) print("Claiming the GAS...") claim_tx, relayed = ClaimGas(self.wallet, require_password=False) self.wait_for_tx(claim_tx) # Finally, need to rebuild the wallet self.wallet.Rebuild() print("\nAll done!") print("- WIF key: %s" % wif) print("- Wallet file: %s" % self.wallet_fn) print("- Wallet pwd: %s" % self.wallet_pwd) if self.wif_fn: with open(self.wif_fn, "w") as f: f.write(wif) self.quit()
def run(self): dbloop = task.LoopingCall(Blockchain.Default().PersistBlocks) dbloop.start(.1) Blockchain.Default().PersistBlocks() while Blockchain.Default().Height < 2: print("Waiting for prompt to sync...") time.sleep(1) tokens = [(Token.Neo, 'NEO'), (Token.Default, ' cli. Type '), (Token.Command, "'help' "), (Token.Default, 'to get started')] print_tokens(tokens, self.token_style) print("\n") timebase = time.time() while self.go_on: try: if len(self.mycommands) > 0: timenow = time.time() if timenow - timebase > 3: #wait 3 seconds timebase = timenow result = self.mycommands.pop() else: time.sleep(0.5) # slow refresh continue #time.sleep(3) else: 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) # Control-D pressed: quit #print("result=",result) #print("mycommands ->", self.mycommands) except EOFError: 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': time.sleep(2) # consolidate chain 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': tx = self.do_import(arguments) # Wait until transaction is on blockchain if tx is not None: self.wait_for_tx(tx) elif command == 'export': self.do_export(arguments) elif command == 'wallet': self.show_wallet(arguments) elif command == 'send': tx = self.do_send(arguments) if tx is not None: if tx is not 0: self.wait_for_tx(tx) 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': tx = self.show_contract_state(arguments) elif command == 'testinvoke': tx = self.test_invoke_contract(arguments) # Wait until transaction is on blockchain if tx is not None: self.wait_for_tx(tx) elif command == 'mem': self.show_mem() elif command == 'nodes' or command == 'node': self.show_nodes() elif command == 'state': self.show_state() elif command == 'debugstorage': self.handle_debug_storage(arguments) 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()
def test_deploy_and_invoke(deploy_script, invoke_args, wallet, from_addr=None, min_fee=DEFAULT_MIN_FEE, invocation_test_mode=True, debug_map=None, invoke_attrs=None, owners=None): bc = GetBlockchain() accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState) assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState) validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState) contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState) storages = DBCollection(bc._db, DBPrefix.ST_Storage, StorageItem) if settings.USE_DEBUG_STORAGE: debug_storage = DebugStorage.instance() storages = DBCollection(debug_storage.db, DBPrefix.ST_Storage, StorageItem) storages.DebugStorage = True dtx = InvocationTransaction() dtx.Version = 1 dtx.outputs = [] dtx.inputs = [] dtx.scripts = [] dtx.Script = binascii.unhexlify(deploy_script) if from_addr is not None: from_addr = PromptUtils.lookup_addr_str(wallet, from_addr) try: dtx = wallet.MakeTransaction(tx=dtx, from_addr=from_addr) except (ValueError, TXFeeError): pass 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, unhex=False)) ] dtx.Attributes = make_unique_script_attr(dtx.Attributes) to_dispatch = [] engine = ApplicationEngine(trigger_type=TriggerType.Application, container=dtx, table=script_table, service=service, gas=dtx.Gas, testMode=True) engine.LoadScript(dtx.Script) # first we will execute the test deploy # then right after, we execute the test invoke d_success = engine.Execute() if d_success: items = engine.ResultStack.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() if type(item) is ContractState: contract_state = item break shash = contract_state.Code.ScriptHash() invoke_args, neo_to_attach, gas_to_attach = PromptUtils.get_asset_attachments( invoke_args) invoke_args, no_parse_addresses = PromptUtils.get_parse_addresses( invoke_args) invoke_args.reverse() if '--i' in invoke_args: invoke_args = [] for index, iarg in enumerate(contract_state.Code.ParameterList): param, abort = PromptUtils.gather_param(index, iarg) if abort: return None, [], 0, None else: invoke_args.append(param) invoke_args.reverse() sb = ScriptBuilder() for p in invoke_args: item = PromptUtils.parse_param(p, wallet, parse_addr=no_parse_addresses) if type(item) is list: item.reverse() listlength = len(item) for listitem in item: subitem = PromptUtils.parse_param( listitem, wallet, parse_addr=no_parse_addresses) if type(subitem) is list: subitem.reverse() for listitem2 in subitem: subsub = PromptUtils.parse_param( listitem2, wallet, parse_addr=no_parse_addresses) sb.push(subsub) sb.push(len(subitem)) sb.Emit(PACK) else: sb.push(subitem) 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 = deepcopy(invoke_attrs) if invoke_attrs else [] itx.Script = binascii.unhexlify(out) if len(outputs) < 1 and not owners: contract = wallet.GetDefaultContract() itx.Attributes.append( TransactionAttribute(usage=TransactionAttributeUsage.Script, data=contract.ScriptHash)) itx.Attributes = make_unique_script_attr(itx.Attributes) try: itx = wallet.MakeTransaction(tx=itx, from_addr=from_addr) except (ValueError, TXFeeError): pass context = ContractParametersContext(itx) wallet.Sign(context) if owners: owners = list(owners) for owner in owners: itx.Attributes.append( TransactionAttribute( usage=TransactionAttributeUsage.Script, data=owner)) itx.Attributes = make_unique_script_attr(itx.Attributes) context = ContractParametersContext(itx, isMultiSig=True) if context.Completed: itx.scripts = context.GetScripts() else: logger.warn( "Not gathering signatures for test build. For a non-test invoke that would occur here." ) # if not gather_signatures(context, itx, owners): # return None, [], 0, None # print("gathered signatures %s " % itx.scripts) engine = ApplicationEngine(trigger_type=TriggerType.Application, container=itx, table=script_table, service=service, gas=itx.Gas, testMode=invocation_test_mode) engine.invocation_args = invoke_args engine.LoadScript(itx.Script) engine.LoadDebugInfoForScriptHash(debug_map, shash.Data) i_success = engine.Execute() service.ExecutionCompleted(engine, i_success) to_dispatch = to_dispatch + service.events_to_dispatch for event in to_dispatch: events.emit(event.event_type, event) if i_success: service.TestCommit() if len(service.notifications) > 0: for n in service.notifications: Blockchain.Default().OnNotify(n) logger.info("Used %s Gas " % engine.GasConsumed().ToString()) consumed = engine.GasConsumed() - Fixed8.FromDecimal(10) consumed = consumed.Ceil() if consumed <= Fixed8.Zero(): consumed = min_fee total_ops = engine.ops_processed # set the amount of gas the tx will need itx.Gas = consumed itx.Attributes = [] result = engine.ResultStack.Items return itx, result, total_ops, engine else: print("error executing invoke contract...") else: print("error executing deploy contract.....") service.ExecutionCompleted(engine, False, 'error') return None, [], 0, None
def test_invoke(script, wallet, outputs, withdrawal_tx=None, from_addr=None, min_fee=DEFAULT_MIN_FEE, invoke_attrs=None, owners=None): # print("invoke script %s " % script) if from_addr is not None: from_addr = PromptUtils.lookup_addr_str(wallet, from_addr) bc = GetBlockchain() accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState) assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState) validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState) contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState) storages = DBCollection(bc._db, 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) tx.Attributes = [] if invoke_attrs is None else deepcopy(invoke_attrs) script_table = CachedScriptTable(contracts) service = StateMachine(accounts, validators, assets, contracts, storages, None) if len(outputs) < 1: contract = wallet.GetDefaultContract() tx.Attributes.append( TransactionAttribute(usage=TransactionAttributeUsage.Script, data=contract.ScriptHash)) tx.Attributes = make_unique_script_attr(tx.Attributes) # 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: try: wallet_tx = wallet.MakeTransaction(tx=tx, from_addr=from_addr, skip_fee_calc=True) except ValueError: pass context = ContractParametersContext(wallet_tx) wallet.Sign(context) if owners: owners = list(owners) for owner in owners: # print("contract %s %s" % (wallet.GetDefaultContract().ScriptHash, owner)) if wallet.GetDefaultContract().ScriptHash != owner: wallet_tx.Attributes.append( TransactionAttribute( usage=TransactionAttributeUsage.Script, data=owner)) wallet_tx.Attributes = make_unique_script_attr(tx.Attributes) context = ContractParametersContext(wallet_tx, isMultiSig=True) if context.Completed: wallet_tx.scripts = context.GetScripts() else: logger.warning( "Not gathering signatures for test build. For a non-test invoke that would occur here." ) # if not gather_signatures(context, wallet_tx, owners): # return None, [], 0, None 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) try: 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 = [] if invoke_attrs is None else deepcopy( invoke_attrs) # calculate the required network fee for the tx and compare to fee if wallet_tx.Size() > settings.MAX_FREE_TX_SIZE: req_fee = Fixed8.FromDecimal( settings.FEE_PER_EXTRA_BYTE * (wallet_tx.Size() - settings.MAX_FREE_TX_SIZE)) if req_fee < settings.LOW_PRIORITY_THRESHOLD: req_fee = settings.LOW_PRIORITY_THRESHOLD if net_fee < req_fee: net_fee = req_fee return wallet_tx, net_fee, engine.ResultStack.Items, engine.ops_processed, success # this allows you to to test invocations that fail else: wallet_tx.outputs = outputs wallet_tx.Attributes = [] if invoke_attrs is None else deepcopy( invoke_attrs) return wallet_tx, min_fee, [], engine.ops_processed, success except Exception as e: service.ExecutionCompleted(engine, False, e) return None, None, None, None, False
def InvokeWithTokenVerificationScript(wallet, tx, token, fee=Fixed8.Zero(), invoke_attrs=None): try: wallet_tx = wallet.MakeTransaction(tx=tx, fee=fee, use_standard=True) except ValueError: print("Insufficient funds") return False except TXFeeError as e: print(e) return False if wallet_tx: token_contract_state = Blockchain.Default().GetContract( token.ScriptHash.ToString()) print("token contract %s " % token_contract_state) tx.Attributes = [ TransactionAttribute(usage=TransactionAttributeUsage.Script, data=token.ScriptHash.Data) ] if invoke_attrs: tx.Attributes += invoke_attrs reedeem_script = token_contract_state.Code.Script.hex() # there has to be at least 1 param, and the first # one needs to be a signature param param_list = bytearray(b'\x00\x00') verification_contract = Contract.Create( reedeem_script, param_list, wallet.GetDefaultContract().PublicKeyHash) context = ContractParametersContext(wallet_tx) wallet.Sign(context) context.Add(verification_contract, 0, 0) if context.Completed: wallet_tx.scripts = context.GetScripts() relayed = NodeLeader.Instance().Relay(wallet_tx) if relayed: print("Relayed Tx: %s " % wallet_tx.Hash.ToString()) # if it was relayed, we save tx wallet.SaveTransaction(wallet_tx) return wallet_tx else: print("Could not relay tx %s " % wallet_tx.Hash.ToString()) else: print("Incomplete signature") else: print("Insufficient funds") return False
def main(): 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), 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("--maxpeers", action="store", default=5, help="Max peers to use for P2P Joining") # 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() return if args.port_rpc == args.port_rest: print("Error: --port-rpc and --port-rest cannot be the same") parser.print_help() return if args.logfile and (args.syslog or args.syslog_local): print("Error: Cannot only use logfile or syslog at once") parser.print_help() return # 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() if args.maxpeers: settings.set_max_peers(args.maxpeers) 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") # Disable logging smart contract events settings.set_log_smart_contract_events(False) # Write a PID file to easily quit the service write_pid_file() # Setup Twisted and Klein logging to use the logzero setup observer = STDLibLogObserver(name=logzero.LOGZERO_DEFAULT_LOGGER) globalLogPublisher.addObserver(observer) # Instantiate the blockchain and subscribe to notifications blockchain = LevelDBBlockchain(settings.chain_leveldb_path) Blockchain.RegisterBlockchain(blockchain) dbloop = task.LoopingCall(Blockchain.Default().PersistBlocks) dbloop.start(.1) # Setup twisted reactor, NodeLeader and start the NotificationDB reactor.suggestThreadPoolSize(15) NodeLeader.Instance().Start() NotificationDB.instance().start() # Start a thread with custom code d = threading.Thread(target=custom_background_code) d.setDaemon( True ) # daemonizing the thread will kill it when the main thread is quit d.start() if args.port_rpc: logger.info("Starting json-rpc api server on http://%s:%s" % (args.host, args.port_rpc)) api_server_rpc = JsonRpcApi(args.port_rpc) endpoint_rpc = "tcp:port={0}:interface={1}".format( args.port_rpc, args.host) endpoints.serverFromString(reactor, endpoint_rpc).listen( Site(api_server_rpc.app.resource())) # reactor.listenTCP(int(args.port_rpc), server.Site(api_server_rpc)) # api_server_rpc.app.run(args.host, args.port_rpc) if args.port_rest: logger.info("Starting REST api server on http://%s:%s" % (args.host, args.port_rest)) api_server_rest = RestApi() endpoint_rest = "tcp:port={0}:interface={1}".format( args.port_rest, args.host) endpoints.serverFromString(reactor, endpoint_rest).listen( Site(api_server_rest.app.resource())) # api_server_rest.app.run(args.host, args.port_rest) reactor.run() # After the reactor is stopped, gracefully shutdown the database. logger.info("Closing databases...") NotificationDB.close() Blockchain.Default().Dispose() NodeLeader.Instance().Shutdown()
def test_show_notifications(self): # setup wallet_1_addr = 'AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3' # test with no NotificationDB with patch( 'neo.Implementations.Notifications.NotificationDB.NotificationDB.instance', return_value=None): args = ['notifications', wallet_1_addr] res = CommandShow().execute(args) self.assertFalse(res) # test with no input args = ['notifications'] res = CommandShow().execute(args) self.assertFalse(res) # good test with address args = ['notifications', wallet_1_addr] res = CommandShow().execute(args) self.assertTrue(res) self.assertEqual(len(res), 1) jsn = res[0].ToJson() self.assertEqual(jsn['notify_type'], 'transfer') self.assertEqual(jsn['addr_from'], wallet_1_addr) # test an address with no notifications args = ['notifications', 'AZiE7xfyJALW7KmADWtCJXGGcnduYhGiCX'] res = CommandShow().execute(args) self.assertFalse(res) # good test with contract contract_hash = "31730cc9a1844891a3bafd1aa929a4142860d8d3" args = ['notifications', contract_hash] res = CommandShow().execute(args) self.assertTrue(res) self.assertEqual(len(res), 1) jsn = res[0].ToJson() self.assertEqual(jsn['notify_type'], 'transfer') self.assertIn(contract_hash, jsn['contract']) # good test with contract 0x hash contract_hash = "0x31730cc9a1844891a3bafd1aa929a4142860d8d3" args = ['notifications', contract_hash] res = CommandShow().execute(args) self.assertTrue(res) self.assertEqual(len(res), 1) jsn = res[0].ToJson() self.assertEqual(jsn['notify_type'], 'transfer') self.assertEqual(contract_hash, jsn['contract']) # test contract not on the blockchain contract_hash = "3a4acd3647086e7c44398aac0349802e6a171129" # NEX token hash args = ['notifications', contract_hash] res = CommandShow().execute(args) self.assertFalse(res) # good test with block index args = ['notifications', "12337"] res = CommandShow().execute(args) self.assertTrue(res) self.assertEqual(len(res), 1) jsn = res[0].ToJson() self.assertEqual(jsn['notify_type'], 'transfer') self.assertEqual(jsn['block'], 12337) # test block with no notifications args = ['notifications', "1"] res = CommandShow().execute(args) self.assertFalse(res) # test bad block index = Blockchain.Default().Height + 1 args = ['notifications', str(index)] res = CommandShow().execute(args) self.assertFalse(res) # test invalid input args = ['notifications', "blah"] res = CommandShow().execute(args) self.assertFalse(res)
def quit(self): print('Shutting down. This may take a bit...') self.go_on = False Blockchain.Default().Dispose() reactor.stop() NodeLeader.Instance().Shutdown()
def ExecutionCompleted(self, engine, success, error=None): height = Blockchain.Default().Height + 1 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 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()
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("-o", "--output", help="Where to save output file") parser.add_argument("-t", "--totalblocks", help="Total blocks to export", type=int) 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 not args.output: raise Exception("Please specify an output path") file_path = args.output # Instantiate the blockchain and subscribe to notifications blockchain = LevelDBBlockchain(settings.chain_leveldb_path) Blockchain.RegisterBlockchain(blockchain) chain = Blockchain.Default() with open(file_path, 'wb') as file_out: total = Blockchain.Default().Height - 1 if args.totalblocks: total = args.totalblocks total_block_output = total.to_bytes(4, 'little') print("Using network %s " % settings.net_name) print("Will export %s blocks to %s " % (total, file_path)) file_out.write(total_block_output) for index in trange(total, desc='Exporting blocks:', unit=' Block'): block = chain.GetBlockByHeight(index) block.LoadTransactions() output = binascii.unhexlify(block.ToArray()) output_length = len(output).to_bytes(4, 'little') file_out.write(output_length) file_out.write(output) print("Exported %s blocks to %s " % (total, file_path))
def __init__(self, path, passwordKey, create): 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._node = RemoteNode(url=TEST_NODE) self._current_height = 0 self.BuildDatabase() passwordHash = hashlib.sha256(passwordKey.encode('utf-8')).digest() master = AES.new(passwordHash, 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('Version') { Version.Major, Version.Minor, Version.Build, Version.Revision }.Select(p => BitConverter.GetBytes(p)).SelectMany(p => p).ToArray()); 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.encode('utf-8')) if passwordHash is not None and passwordHash != hashlib.sha256( passwordKey.encode('utf-8')).digest(): raise Exception("Incorrect Password") self._iv = self.LoadStoredData('IV') master_stored = self.LoadStoredData('MasterKey') aes = AES.new(hkey.digest(), 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._coins = self.LoadCoins() try: h = int(self.LoadStoredData('Height')) self._current_height = h except Exception as e: print("couldnt load height data %s " % e) self._current_height = 0 # self._current_height = 470000 del passwordKey
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()