public NexusAPI(Nexus nexus, Mempool mempool = null) { Throw.IfNull(nexus, nameof(nexus)); Nexus = nexus; Mempool = mempool; var methodInfo = GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (var entry in methodInfo) { if (entry.ReturnType != typeof(IAPIResult)) { continue; } if (entry.Name == nameof(Execute)) { continue; } var temp = new APIEntry(this, entry); if (temp.ReturnType != null) { _methods[entry.Name.ToLower()] = temp; } } }
private void InitMainNode() { var log = new ConsoleLogger(); var seeds = new List <string>(); Console.ForegroundColor = ConsoleColor.DarkGray; string wif = nexusWif; int port = 7077; var node_keys = KeyPair.FromWIF(wif); var simulator = new ChainSimulator(node_keys, 1234, -1); nexus = simulator.Nexus; /* * for (int i = 0; i < 100; i++) * { * simulator.GenerateRandomBlock(); * } */ // mempool setup mempool = new Mempool(node_keys, nexus, Mempool.MinimumBlockTime); mempool.Start(); // node setup var node = new Node(nexus, mempool, node_keys, port, seeds, log); log.Message("Phantasma Node address: " + node_keys.Address.Text); node.Start(); }
private void InitMainNode(int _port = 7077) { var log = new ConsoleLogger(); string wif = nexusWif; int port = _port; var node_keys = PhantasmaKeys.FromWIF(wif); var nexus = new Nexus("simnet", null, null); nexus.SetOracleReader(new OracleSimulator(nexus)); var simulator = new NexusSimulator(nexus, node_keys, 1234); // mempool setup mempool = new Mempool(nexus, Mempool.MinimumBlockTime, 1, System.Text.Encoding.UTF8.GetBytes("TEST")); mempool.SetKeys(node_keys); mempool.Start(); // node setup node = new Node("test node", nexus, mempool, node_keys, port, PeerCaps.Mempool, Enumerable.Empty <String>(), log); log.Message("Phantasma Node address: " + node_keys.Address.Text); node.Start(); }
public Node(string version, Nexus nexus, Mempool mempool, PhantasmaKeys keys, string publicHost, int port, PeerCaps caps, IEnumerable <string> seeds, Logger log) { if (mempool != null) { Throw.If(!caps.HasFlag(PeerCaps.Mempool), "mempool not included in caps but a mempool instance was passed"); Throw.If(keys.Address != mempool.ValidatorAddress, "invalid mempool"); } else { Throw.If(caps.HasFlag(PeerCaps.Mempool), "mempool included in caps but mempool instance is null"); } this.Logger = Logger.Init(log); this.Version = version; this.Nexus = nexus; this.Port = port; this.Keys = keys; this.Capabilities = caps; if (Capabilities.HasFlag(PeerCaps.Sync)) { this.Nexus.AddPlugin(new NodePlugin(this)); } if (Capabilities.HasFlag(PeerCaps.Mempool)) { Throw.IfNull(mempool, nameof(mempool)); this._mempool = mempool; } else { this._mempool = null; } Throw.IfNullOrEmpty(publicHost, nameof(publicHost)); Throw.If(publicHost.Contains(":"), "invalid host, protocol or port number should not be included"); this.Host = publicHost; this.PublicEndpoint = $"tcp:{publicHost}:{port}"; if (this.Capabilities.HasFlag(PeerCaps.Sync)) { QueueEndpoints(seeds); // TODO this is a security issue, later change this to be configurable and default to localhost var bindAddress = IPAddress.Any; listener = new TcpListener(bindAddress, port); if (seeds.Any()) { // temporary HACK var baseURL = "http:" + seeds.First().Split(':')[1]; ProxyURL = baseURL + ":7078/api"; } } }
public Transaction BroadcastTransaction(Transaction tx) { var h = tx.GetHash(); Mempool.Add(h, tx); OnNewTransaction(tx); return(tx); }
public MempoolTests() { _hashProvider = new HashProvider(HashingAlgorithm.GetAlgorithmMetadata("blake2b-256")); _memPool = new Mempool(Substitute.For <IMempoolService <PublicEntryDao> >()); _mapperProvider = new TestMapperProvider(); _mempoolItem = TransactionHelper .GetPublicTransaction().PublicEntry .ToDao <PublicEntry, PublicEntryDao>(_mapperProvider); }
protected override void OnStart() { Console.CancelKeyPress += delegate { this.Terminate(); }; ValidateConfig(); Version = Assembly.GetAssembly(typeof(Spook)).GetVersion(); _nodeKeys = SetupNodeKeys(); if (!SetupNexus()) { this.OnStop(); return; } SetupOracleApis(); if (Settings.Node.HasMempool && !Settings.Node.Readonly) { _mempool = SetupMempool(); } _peerCaps = SetupPeerCaps(); _node = SetupNode(); _nexusApi = SetupNexusApi(); if (_node != null && Settings.App.NodeStart) { _node.StartInThread(); } _commandDispatcher = SetupCommandDispatcher(); if (Settings.Simulator.Enabled) { StartSimulator(_commandDispatcher); } else { MakeReady(_commandDispatcher); } if (!string.IsNullOrEmpty(Settings.Oracle.Swaps)) { _tokenSwapper = StartTokenSwapper(); } }
public Transaction GiveMoney(Script scriptPubKey, Money value) { var tx = new Transaction(); tx.Outputs.Add(new TxOut(value, scriptPubKey)); var h = tx.GetHash(); Mempool.Add(h, tx); OnNewTransaction(tx); return(tx); }
public MempoolPlugin(Mempool mempool, Logger logger, int periodInSeconds) { this.Mempool = mempool; this.logger = logger; this.periodInSeconds = periodInSeconds; this.gui = logger as ConsoleGUI; if (gui != null) { this.graph = new Graph(); gui.SetChannelGraph(Channel, graph); } }
public Node(string version, Nexus nexus, Mempool mempool, PhantasmaKeys keys, int port, PeerCaps caps, IEnumerable <string> seeds, Logger log) { Throw.If(keys.Address != mempool.ValidatorAddress, "invalid mempool"); this.Logger = Logger.Init(log); this.Version = version; this.Nexus = nexus; this.Port = port; this.Keys = keys; this.Capabilities = caps; if (Capabilities.HasFlag(PeerCaps.Sync)) { this.Nexus.AddPlugin(new NodePlugin(this)); } if (Capabilities.HasFlag(PeerCaps.Mempool)) { Throw.IfNull(mempool, nameof(mempool)); this._mempool = mempool; } else { this._mempool = null; } var ip = GetPublicIP(); Throw.IfNull(ip, nameof(ip)); this.PublicIP = ip.ToString(); QueueEndpoints(seeds.Select(seed => ParseEndpoint(seed))); // TODO this is a security issue, later change this to be configurable and default to localhost var bindAddress = IPAddress.Any; listener = new TcpListener(bindAddress, port); client = new TcpClient(); }
public Node(Nexus nexus, Mempool mempool, KeyPair keys, int port, IEnumerable <string> seeds, Logger log) { Throw.IfNull(mempool, nameof(mempool)); Throw.If(keys.Address != mempool.ValidatorAddress, "invalid mempool"); this.Nexus = nexus; this.Port = port; this.Keys = keys; this.Logger = Logger.Init(log); this._mempool = mempool; QueueEndpoints(seeds.Select(seed => ParseEndpoint(seed))); // TODO this is a security issue, later change this to be configurable and default to localhost var bindAddress = IPAddress.Any; listener = new TcpListener(bindAddress, port); client = new TcpClient(); }
private void InitMainNode(int _port = 7077) { string wif = nexusWif; int port = _port; var node_keys = PhantasmaKeys.FromWIF(wif); var nexus = new Nexus("simnet", null, null); nexus.SetOracleReader(new OracleSimulator(nexus)); var simulator = new NexusSimulator(nexus, node_keys, 1234); // mempool setup mempool = new Mempool(nexus, Mempool.MinimumBlockTime, 1, System.Text.Encoding.UTF8.GetBytes("TEST")); mempool.SetKeys(node_keys); mempool.StartInThread(); // node setup node = new Node("test node", nexus, mempool, node_keys, "localhost", port, PeerCaps.Mempool, Enumerable.Empty <String>(), new DebugLogger()); node.StartInThread(); }
public Node(string version, Nexus nexus, Mempool mempool, PhantasmaKeys keys, int port, PeerCaps caps, IEnumerable <string> seeds, Logger log) { Throw.If(keys.Address != mempool.ValidatorAddress, "invalid mempool"); this.Version = version; this.Nexus = nexus; this.Port = port; this.Keys = keys; this.Capabilities = caps; if (Capabilities.HasFlag(PeerCaps.Events)) { this.Nexus.AddPlugin(new NodePlugin(this)); } if (Capabilities.HasFlag(PeerCaps.Mempool)) { Throw.IfNull(mempool, nameof(mempool)); this._mempool = mempool; } else { this._mempool = null; } // obtains the public IP of the node. This might not be the most sane way to do it... this.PublicIP = new WebClient().DownloadString("http://icanhazip.com").Trim(); Throw.IfNullOrEmpty(PublicIP, nameof(PublicIP)); this.Logger = Logger.Init(log); QueueEndpoints(seeds.Select(seed => ParseEndpoint(seed))); // TODO this is a security issue, later change this to be configurable and default to localhost var bindAddress = IPAddress.Any; listener = new TcpListener(bindAddress, port); client = new TcpClient(); }
private void InitializeInstance() { Concensus = new Consensus(); Blockchain = new Blockchain(); Miner = new Miner(); Network = new Network(); Accounts = new Accounts(); Mempool = new Mempool(); Wallet = new Wallet(); Client.Socket.On(Socket.EVENT_CONNECT, () => { Client.Connected = true; }); Client.Socket.On(Socket.EVENT_DISCONNECT, () => { Client.Connected = false; }); Client.Socket.On("LifeCheck", (jData) => { JObject jObject = (JObject)jData; var deserialize = jObject.ToObject <LifeCheckStruct>(); if (LifeCheck != null) { LifeCheck.Invoke(deserialize); } }); }
private void InitMainNode() { var log = new ConsoleLogger(); string wif = nexusWif; int port = 7077; var node_keys = KeyPair.FromWIF(wif); var simulator = new ChainSimulator(node_keys, 1234); nexus = simulator.Nexus; // mempool setup mempool = new Mempool(node_keys, nexus, Mempool.MinimumBlockTime); mempool.Start(); // node setup node = new Node(nexus, mempool, node_keys, port, Enumerable.Empty <String>(), log); log.Message("Phantasma Node address: " + node_keys.Address.Text); node.Start(); }
private void Forward(IxgbeDevice rxDev, int rxQueue, IxgbeDevice txDev, int txQueue, Span <PacketBuffer> buffers) { var rxBuffCount = rxDev.RxBatch(rxQueue, buffers); if (rxBuffCount > 0) { var rxBuffers = buffers.Slice(0, rxBuffCount); //Touch all buffers to simulate a realistic scenario foreach (var buffer in rxBuffers) { buffer.Touch(); } var txBuffCount = txDev.TxBatch(txQueue, rxBuffers); _mempool = (_mempool == null) ? Mempool.FindPool(rxBuffers[0].MempoolId) : _mempool; //Drop unsent packets foreach (var buffer in rxBuffers.Slice(txBuffCount)) { _mempool.FreeBuffer(buffer); } } }
private void InitMempool() { _mempool = MemoryHelper.AllocateMempool(BuffersCount); //Pre-fill all our packet buffers with some templates that can be modified later var buffers = new PacketBuffer[BuffersCount]; for (int i = 0; i < BuffersCount; i++) { var buffer = _mempool.GetPacketBuffer(); buffer.Size = (uint)PacketData.Length; buffer.WriteData(0, PacketData); var ipData = buffer.CopyData(14, 20); buffer.WriteData(24, (short)CalcIpChecksum(ipData)); buffers[i] = buffer; } //Return them all to the mempool, all future allocations will return buffers with the data set above foreach (var buffer in buffers) { _mempool.FreeBuffer(buffer); } }
private Mempool SetupMempool() { var mempool = new Mempool(_nexus , Settings.Node.BlockTime , Settings.Node.MinimumFee , System.Text.Encoding.UTF8.GetBytes(TxIdentifier) , 0 , Logger , Settings.Node.ProfilerPath ); if (Settings.Node.MempoolLog) { mempool.OnTransactionFailed += Mempool_OnTransactionFailed; mempool.OnTransactionAdded += (hash) => Logger.Message($"Received transaction {hash}"); mempool.OnTransactionCommitted += (hash) => Logger.Message($"Commited transaction {hash}"); mempool.OnTransactionDiscarded += (hash) => Logger.Message($"Discarded transaction {hash}"); } if (Settings.App.NodeStart) { mempool.StartInThread(ThreadPriority.AboveNormal); } return(mempool); }
protected override void OnStart() { Console.CancelKeyPress += delegate { this.Terminate(); }; ValidateConfig(); Version = Assembly.GetAssembly(typeof(Spook)).GetVersion(); _nodeKeys = SetupNodeKeys(); if (Settings.Node.Mode != NodeMode.Proxy && !SetupNexus()) { this.OnStop(); return; } SetupOracleApis(); if (Settings.Node.HasMempool && !Settings.Node.Readonly) { _mempool = SetupMempool(); } if (Settings.Node.Mode != NodeMode.Proxy) { _availablePorts.Add(new PeerPort("sync", Settings.Node.NodePort)); } if (Settings.Node.HasRpc) { _availablePorts.Add(new PeerPort("rpc", Settings.Node.RpcPort)); } if (Settings.Node.HasRest) { _availablePorts.Add(new PeerPort("rest", Settings.Node.RestPort)); } _peerCaps = SetupPeerCaps(); _node = SetupNode(); _nexusApi = SetupNexusApi(); if (_node != null && Settings.App.NodeStart) { if (_peerCaps.HasFlag(PeerCaps.Sync) && Settings.Node.NodeHost.Contains("localhost")) { Logger.Warning($"This node host external endpoint is not properly configured and it won't appear on other nodes GetPeers API call."); } _node.StartInThread(); } _commandDispatcher = SetupCommandDispatcher(); if (Settings.Simulator.Enabled) { StartSimulator(_commandDispatcher); } else { MakeReady(_commandDispatcher); } var enabledSwapPlatforms = Settings.Oracle.SwapPlatforms.Select(x => x.Chain != SwapPlatformChain.Phantasma && x.Enabled); if (enabledSwapPlatforms.Any()) { _tokenSwapper = StartTokenSwapper(); } else { Logger.Warning("No swap platforms found in config, token swapper won't be available"); } }
public static async Task FlushAll() { await Mempool.Flush(); await Peers.Flush(); }
public override int TxBatch(int queueId, Span <PacketBuffer> buffers) { if (queueId < 0 || queueId >= RxQueues.Length) { throw new ArgumentOutOfRangeException("Queue id out of bounds"); } var queue = TxQueues[queueId] as IxgbeTxQueue; ushort cleanIndex = queue.CleanIndex; ushort currentIndex = (ushort)queue.Index; var cmdTypeFlags = IxgbeDefs.ADVTXD_DCMD_EOP | IxgbeDefs.ADVTXD_DCMD_RS | IxgbeDefs.ADVTXD_DCMD_IFCS | IxgbeDefs.ADVTXD_DCMD_DEXT | IxgbeDefs.ADVTXD_DTYP_DATA; //All packet buffers that will be handled here will belong to the same mempool Mempool pool = null; //Step 1: Clean up descriptors that were sent out by the hardware and return them to the mempool //Start by reading step 2 which is done first for each packet //Cleaning up must be done in batches for performance reasons, so this is unfortunately somewhat complicated while (true) { //currentIndex is always ahead of clean (invariant of our queue) int cleanable = currentIndex - cleanIndex; if (cleanable < 0) { cleanable = queue.EntriesCount + cleanable; } if (cleanable < TxCleanBatch) { break; } //Calculate the index of the last transcriptor in the clean batch //We can't check all descriptors for performance reasons int cleanupTo = cleanIndex + TxCleanBatch - 1; if (cleanupTo >= queue.EntriesCount) { cleanupTo -= queue.EntriesCount; } var descAddr = queue.GetDescriptorAddress((ushort)cleanupTo); uint status = queue.ReadWbStatus(descAddr); //Hardware sets this flag as soon as it's sent out, we can give back all bufs in the batch back to the mempool if ((status & IxgbeDefs.ADVTXD_STAT_DD) != 0) { int i = cleanIndex; while (true) { var packetBuffer = new PacketBuffer(queue.VirtualAddresses[i]); if (pool == null) { pool = Mempool.FindPool(packetBuffer.MempoolId); if (pool == null) { throw new NullReferenceException("Could not find mempool with id specified by PacketBuffer"); } } pool.FreeBufferFast(packetBuffer); if (i == cleanupTo) { break; } i = WrapRing(i, queue.EntriesCount); } //Next descriptor to be cleaned up is one after the one we just cleaned cleanIndex = (ushort)WrapRing(cleanupTo, queue.EntriesCount); } //Clean the whole batch or nothing. This will leave some packets in the queue forever //if you stop transmitting but that's not a real concern else { break; } } queue.CleanIndex = cleanIndex; //Step 2: Send out as many of our packets as possible int sent; for (sent = 0; sent < buffers.Length; sent++) { var descAddr = queue.GetDescriptorAddress(currentIndex); ushort nextIndex = WrapRing(currentIndex, (ushort)queue.EntriesCount); //We are full if the next index is the one we are trying to reclaim if (cleanIndex == nextIndex) { break; } var buffer = buffers[sent]; //Remember virtual address to clean it up later queue.VirtualAddresses[currentIndex] = buffer.VirtualAddress; queue.Index = WrapRing(queue.Index, queue.EntriesCount); //NIC reads from here queue.WriteBufferAddress(descAddr, buffer.PhysicalAddress + PacketBuffer.DataOffset); //Always the same flags: One buffer (EOP), advanced data descriptor, CRC offload, data length var bufSize = buffer.Size; queue.WriteCmdTypeLength(descAddr, cmdTypeFlags | bufSize); //No fancy offloading - only the total payload length //implement offloading flags here: // * ip checksum offloading is trivial: just set the offset // * tcp/udp checksum offloading is more annoying, you have to precalculate the pseudo-header checksum queue.WriteOlInfoStatus(descAddr, bufSize << (int)IxgbeDefs.ADVTXD_PAYLEN_SHIFT); currentIndex = nextIndex; } //Send out by advancing tail, i.e. pass control of the bus to the NIC SetReg(IxgbeDefs.TDT((uint)queueId), (uint)queue.Index); return(sent); }
public MempoolTests() { _memPool = new Mempool(Substitute.For <IMempoolRepository <MempoolDocument> >()); _transactionBroadcast = TransactionHelper.GetPublicTransaction(); }
public void GenerateRandomBlock(Mempool mempool = null) { BeginBlock(); int transferCount = 1 + _rnd.Next() % 10; int tries = 0; while (tries < 10000) { if (transactions.Count >= transferCount) { break; } tries++; var source = _keys[_rnd.Next() % _keys.Count]; if (usedAddresses.Contains(source.Address)) { continue; } var prevTxCount = transactions.Count; var sourceChain = Nexus.RootChain; var fee = 9999; string tokenSymbol; switch (_rnd.Next() % 4) { case 1: tokenSymbol = DomainSettings.FiatTokenSymbol; break; //case 2: token = Nexus.FuelTokenSymbol; break; default: tokenSymbol = DomainSettings.StakingTokenSymbol; break; } switch (_rnd.Next() % 7) { /* * // side-chain send * case 1: * { * var sourceChainList = Nexus.Chains.ToArray(); * sourceChain = Nexus.GetChainByName( sourceChainList[_rnd.Next() % sourceChainList.Length]); * * var targetChainList = Nexus.Chains.Select(x => Nexus.GetChainByName(x)).Where(x => Nexus.GetParentChainByName(x.Name) == sourceChain.Name || Nexus.GetParentChainByName(sourceChain.Name) == x.Name).ToArray(); * var targetChain = targetChainList[_rnd.Next() % targetChainList.Length]; * * var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, DomainSettings.FuelTokenDecimals); * * var tokenBalance = sourceChain.GetTokenBalance(sourceChain.Storage, tokenSymbol, source.Address); * var fuelBalance = sourceChain.GetTokenBalance(sourceChain.Storage, DomainSettings.FuelTokenSymbol, source.Address); * * var expectedTotal = total; * if (tokenSymbol == DomainSettings.FuelTokenSymbol) * { * expectedTotal += fee; * } * * var sideFee = 0; * if (tokenSymbol != DomainSettings.FuelTokenSymbol) * { * sideFee = fee; * } * * if (tokenBalance > expectedTotal && fuelBalance > fee + sideFee) * { * Logger.Debug($"Rnd.SideChainSend: {total} {tokenSymbol} from {source.Address}"); * GenerateSideChainSend(source, tokenSymbol, sourceChain, source.Address, targetChain, total, sideFee); * } * break; * } * * // side-chain receive * case 2: * { * if (_pendingBlocks.Any()) * { * var pendingBlock = _pendingBlocks.First(); * * if (mempool == null || Nexus.GetConfirmationsOfHash(pendingBlock.hash) > 0) * { * * var balance = pendingBlock.destChain.GetTokenBalance(pendingBlock.destChain.Storage, pendingBlock.tokenSymbol, source.Address); * if (balance > 0) * { * Logger.Message($"...Settling {pendingBlock.sourceChain.Name}=>{pendingBlock.destChain.Name}: {pendingBlock.hash}"); * GenerateSideChainSettlement(source, pendingBlock.sourceChain, pendingBlock.destChain, pendingBlock.hash); * } * } * } * * break; * } */ /* * // stable claim * case 3: * { * sourceChain = bankChain; * tokenSymbol = Nexus.FuelTokenSymbol; * * var balance = sourceChain.GetTokenBalance(tokenSymbol, source.Address); * * var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, Nexus.FuelTokenDecimals - 1); * * if (balance > total + fee) * { * Logger.Debug($"Rnd.StableClaim: {total} {tokenSymbol} from {source.Address}"); * GenerateStableClaim(source, sourceChain, total); * } * * break; * } * * // stable redeem * case 4: * { * sourceChain = bankChain; * tokenSymbol = Nexus.FiatTokenSymbol; * * var tokenBalance = sourceChain.GetTokenBalance(tokenSymbol, source.Address); * var fuelBalance = sourceChain.GetTokenBalance(Nexus.FuelTokenSymbol, source.Address); * * var rate = (BigInteger) bankChain.InvokeContract("bank", "GetRate", Nexus.FuelTokenSymbol); * var total = tokenBalance / 10; * if (total >= rate && fuelBalance > fee) * { * Logger.Debug($"Rnd.StableRedeem: {total} {tokenSymbol} from {source.Address}"); * GenerateStableRedeem(source, sourceChain, total); * } * * break; * }*/ // name register case 5: { sourceChain = this.Nexus.RootChain; tokenSymbol = DomainSettings.FuelTokenSymbol; var token = Nexus.GetTokenInfo(Nexus.RootStorage, tokenSymbol); var balance = sourceChain.GetTokenBalance(sourceChain.Storage, token, source.Address); if (balance > fee + AccountContract.RegistrationCost && !pendingNames.Contains(source.Address)) { var randomName = accountNames[_rnd.Next() % accountNames.Length]; switch (_rnd.Next() % 10) { case 1: case 2: randomName += (_rnd.Next() % 10).ToString(); break; case 3: case 4: case 5: randomName += (10 + _rnd.Next() % 90).ToString(); break; case 6: randomName += (100 + _rnd.Next() % 900).ToString(); break; } var currentName = Nexus.RootChain.LookUpAddressName(Nexus.RootStorage, source.Address); if (currentName == ValidationUtils.ANONYMOUS) { var lookup = Nexus.LookUpName(Nexus.RootStorage, randomName); if (lookup.IsNull) { Logger.Debug($"Rnd.GenerateAccount: {source.Address} => {randomName}"); GenerateAccountRegistration(source, randomName); } } } break; } // normal transfer default: { var temp = _rnd.Next() % 5; Address targetAddress; if ((_keys.Count < 2 || temp == 0) && _keys.Count < 2000) { var key = PhantasmaKeys.Generate(); _keys.Add(key); targetAddress = key.Address; } else { targetAddress = _keys[_rnd.Next() % _keys.Count].Address; } if (source.Address != targetAddress) { var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, DomainSettings.FuelTokenDecimals - 1); var token = Nexus.GetTokenInfo(Nexus.RootStorage, tokenSymbol); var tokenBalance = sourceChain.GetTokenBalance(sourceChain.Storage, token, source.Address); var fuelToken = Nexus.GetTokenInfo(Nexus.RootStorage, DomainSettings.FuelTokenSymbol); var fuelBalance = sourceChain.GetTokenBalance(sourceChain.Storage, fuelToken, source.Address); var expectedTotal = total; if (tokenSymbol == DomainSettings.FuelTokenSymbol) { expectedTotal += fee; } if (tokenBalance > expectedTotal && fuelBalance > fee) { Logger.Message($"Rnd.Transfer: {total} {tokenSymbol} from {source.Address} to {targetAddress}"); GenerateTransfer(source, targetAddress, sourceChain, tokenSymbol, total); } } break; } } } if (transactions.Count > 0) { EndBlock(mempool); } else { CancelBlock(); } }
public IEnumerable <Block> EndBlock(Mempool mempool = null) { if (!blockOpen) { throw new Exception("Simulator block not open"); } usedAddresses.Clear(); blockOpen = false; var blocks = new List <Block>(); if (txChainMap.Count > 0) { var chains = txChainMap.Values.Distinct(); foreach (var chain in chains) { var hashes = txChainMap.Where((p) => p.Value == chain).Select(x => x.Key); if (hashes.Any()) { var txs = new List <Transaction>(); foreach (var hash in hashes) { txs.Add(txHashMap[hash]); } uint nextHeight = chain.LastBlock != null ? chain.LastBlock.Height + 1 : Chain.InitialHeight; var prevHash = chain.LastBlock != null ? chain.LastBlock.Hash : Hash.Null; var block = new Block(nextHeight, chain.Address, CurrentTime, hashes, prevHash); bool submitted; if (mempool != null) { submitted = true; foreach (var tx in txs) { try { mempool.Submit(tx); } catch { submitted = false; break; } } } else { try { chain.AddBlock(block, txs, null); submitted = true; } catch (Exception e) { submitted = false; } } if (submitted) { blocks.Add(block); CurrentTime += TimeSpan.FromMinutes(45); // add the finished block hash to each pending side chain tx if (_pendingEntries.Count > 0) { foreach (var entry in _pendingEntries.Values) { if (entry.sourceChain != chain) { continue; } var pendingBlock = new SideChainPendingBlock() { sourceChain = entry.sourceChain, destChain = entry.destChain, hash = block.Hash, tokenSymbol = entry.tokenSymbol }; _pendingBlocks.Add(pendingBlock); Logger.Debug($"...Sending {entry.sourceChain.Name}=>{entry.destChain.Name}: {block.Hash}"); } } Logger.Message($"End block #{step} @ {chain.Name} chain: {block.Hash}"); } else { throw new Exception($"add block @ {chain.Name} failed"); } } } _pendingEntries.Clear(); return(blocks); } return(Enumerable.Empty <Block>()); }
public CLI(string[] args) { var culture = new CultureInfo("en-US"); CultureInfo.DefaultThreadCurrentCulture = culture; var seeds = new List <string>(); var settings = new Arguments(args); /* * for (int i = 0; i < 20; i++) * { * var k = KeyPair.Generate(); * Console.WriteLine(k.ToWIF() + " => " + k.Address.Text); * }*/ var useGUI = settings.GetBool("gui.enabled", true); if (useGUI) { gui = new ConsoleGUI(); logger = gui; } else { gui = null; logger = new ConsoleLogger(); } string mode = settings.GetString("node.mode", "validator"); bool hasRPC = settings.GetBool("rpc.enabled", false); bool hasREST = settings.GetBool("rest.enabled", false); string wif = settings.GetString("node.wif"); var nexusName = settings.GetString("nexus.name", "simnet"); switch (mode) { case "sender": string host = settings.GetString("sender.host"); int threadCount = settings.GetInt("sender.threads", 8); int addressesPerSender = settings.GetInt("sender.addressCount", 100); RunSender(wif, host, threadCount, addressesPerSender); Console.WriteLine("Sender finished operations."); return; case "validator": break; default: { logger.Error("Unknown mode: " + mode); return; } } int defaultPort = 0; for (int i = 0; i < validatorWIFs.Length; i++) { if (validatorWIFs[i] == wif) { defaultPort = (7073 + i); } } if (defaultPort == 0) { defaultPort = (7073 + validatorWIFs.Length); } int port = settings.GetInt("node.port", defaultPort); var defaultStoragePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Storage"; var storagePath = settings.GetString("storage.path", defaultStoragePath); storagePath = storagePath.Replace("\\", "/"); if (!storagePath.EndsWith('/')) { storagePath += '/'; } var storageFix = settings.GetBool("storage.fix", false); // TODO remove this later if (storageFix) { if (Directory.Exists(storagePath)) { logger.Warning("Storage fix enabled... Cleaning up all storage..."); var di = new DirectoryInfo(storagePath); foreach (FileInfo file in di.EnumerateFiles()) { file.Delete(); } } } logger.Message("Storage path: " + storagePath); var node_keys = KeyPair.FromWIF(wif); nexus = new Nexus(logger, (name) => new BasicDiskStore(storagePath + name + ".txt")); bool bootstrap = false; if (wif == validatorWIFs[0]) { if (!nexus.Ready) { logger.Debug("Boostraping nexus..."); bootstrap = true; if (!nexus.CreateGenesisBlock(nexusName, node_keys, Timestamp.Now)) { throw new ChainException("Genesis block failure"); } logger.Debug("Genesis block created: " + nexus.GenesisHash); } } else { //nexus = new Nexus(nexusName, genesisAddress, logger); nexus = new Nexus(logger); seeds.Add("127.0.0.1:7073"); } // TODO this should be later optional to enable nexus.AddPlugin(new ChainAddressesPlugin()); nexus.AddPlugin(new TokenTransactionsPlugin()); nexus.AddPlugin(new AddressTransactionsPlugin()); nexus.AddPlugin(new UnclaimedTransactionsPlugin()); running = true; // mempool setup int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime); this.mempool = new Mempool(node_keys, nexus, blockTime, ReadFromOracle); mempool.Start(ThreadPriority.AboveNormal); mempool.OnTransactionFailed += Mempool_OnTransactionFailed; api = new NexusAPI(nexus, mempool); // RPC setup if (hasRPC) { int rpcPort = settings.GetInt("rpc.port", 7077); logger.Message($"RPC server listening on port {rpcPort}..."); var rpcServer = new RPCServer(api, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text)); rpcServer.Start(ThreadPriority.AboveNormal); } // REST setup if (hasREST) { int restPort = settings.GetInt("rest.port", 7078); logger.Message($"REST server listening on port {restPort}..."); var restServer = new RESTServer(api, "/api", restPort, (level, text) => WebLogMapper("rest", level, text)); restServer.Start(ThreadPriority.AboveNormal); } cryptoCompareAPIKey = settings.GetString("cryptocompare.apikey", ""); if (!string.IsNullOrEmpty(cryptoCompareAPIKey)) { logger.Message($"CryptoCompare API enabled..."); } // node setup this.node = new Node(nexus, mempool, node_keys, port, seeds, logger); node.Start(); if (gui != null) { int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds RegisterPlugin(new TPSPlugin(logger, pluginPeriod)); RegisterPlugin(new RAMPlugin(logger, pluginPeriod)); RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod)); } Console.CancelKeyPress += delegate { Terminate(); }; var dispatcher = new CommandDispatcher(); SetupCommands(dispatcher); bool useSimulator = settings.GetBool("simulator.enabled", false); if (useSimulator && bootstrap) { new Thread(() => { logger.Message("Initializing simulator..."); var simulator = new ChainSimulator(this.nexus, node_keys, 1234); logger.Message("Bootstrapping validators"); simulator.BeginBlock(); for (int i = 1; i < validatorWIFs.Length; i++) { simulator.GenerateTransfer(node_keys, Address.FromWIF(validatorWIFs[i]), this.nexus.RootChain, Nexus.StakingTokenSymbol, UnitConversion.ToBigInteger(50000, Nexus.StakingTokenDecimals)); } simulator.EndBlock(); for (int i = 0; i < 3; i++) { logger.Message("Generating sim block #" + i); simulator.GenerateRandomBlock(); } NachoServer.InitNachoServer(nexus, simulator, node_keys, logger); MakeReady(dispatcher); }).Start(); } else { MakeReady(dispatcher); } this.Run(); }
public void GenerateRandomBlock(Mempool mempool = null) { //Console.WriteLine("begin block #" + Nexus.RootChain.BlockHeight); BeginBlock(); int transferCount = 1 + _rnd.Next() % 10; int tries = 0; while (transactions.Count < transferCount && tries < 1000) { tries++; var source = _keys[_rnd.Next() % _keys.Count]; if (usedAddresses.Contains(source.Address)) { continue; } var prevTxCount = transactions.Count; var sourceChain = Nexus.RootChain; var fee = 9999; Token token; switch (_rnd.Next() % 4) { case 1: token = Nexus.StableToken; break; //case 2: token = Nexus.FuelToken; break; default: token = Nexus.StakingToken; break; } switch (_rnd.Next() % 7) { // side-chain send case 1: { var sourceChainList = Nexus.Chains.ToArray(); sourceChain = sourceChainList[_rnd.Next() % sourceChainList.Length]; var targetChainList = Nexus.Chains.Where(x => x.ParentChain == sourceChain || sourceChain.ParentChain == x).ToArray(); var targetChain = targetChainList[_rnd.Next() % targetChainList.Length]; var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, Nexus.FuelTokenDecimals); var tokenBalance = sourceChain.GetTokenBalance(token, source.Address); var fuelBalance = sourceChain.GetTokenBalance(Nexus.FuelToken, source.Address); var expectedTotal = total; if (token == Nexus.FuelToken) { expectedTotal += fee; } var sideFee = 0; if (token != Nexus.FuelToken) { sideFee = fee; } if (tokenBalance > expectedTotal && fuelBalance > fee + sideFee) { GenerateSideChainSend(source, token, sourceChain, source.Address, targetChain, total, sideFee); } break; } // side-chain receive case 2: { if (_pendingBlocks.Any()) { var pendingBlock = _pendingBlocks.First(); if (mempool == null || Nexus.GetConfirmationsOfHash(pendingBlock.hash) > 0) { var balance = pendingBlock.destChain.GetTokenBalance(pendingBlock.token, source.Address); if (balance > 0) { Logger.Message($"...Settling {pendingBlock.sourceChain.Name}=>{pendingBlock.destChain.Name}: {pendingBlock.hash}"); GenerateSideChainSettlement(source, pendingBlock.sourceChain, pendingBlock.destChain, pendingBlock.hash); } } } break; } // stable claim case 3: { sourceChain = bankChain; token = Nexus.FuelToken; var balance = sourceChain.GetTokenBalance(token, source.Address); var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, Nexus.FuelTokenDecimals - 1); if (balance > total + fee) { GenerateStableClaim(source, sourceChain, total); } break; } // stable redeem case 4: { sourceChain = bankChain; token = Nexus.StableToken; var tokenBalance = sourceChain.GetTokenBalance(token, source.Address); var fuelBalance = sourceChain.GetTokenBalance(Nexus.FuelToken, source.Address); var bankContract = bankChain.FindContract <BankContract>("bank"); var rate = bankContract.GetRate(Nexus.FuelTokenSymbol); var total = tokenBalance / 10; if (total >= rate && fuelBalance > fee) { GenerateStableRedeem(source, sourceChain, total); } break; } // name register case 5: { sourceChain = this.Nexus.RootChain; token = Nexus.FuelToken; var balance = sourceChain.GetTokenBalance(token, source.Address); if (balance > fee + AccountContract.RegistrationCost && !pendingNames.Contains(source.Address)) { var randomName = accountNames[_rnd.Next() % accountNames.Length]; switch (_rnd.Next() % 10) { case 1: case 2: randomName += (_rnd.Next() % 10).ToString(); break; case 3: case 4: case 5: randomName += (10 + _rnd.Next() % 90).ToString(); break; case 6: randomName += (100 + _rnd.Next() % 900).ToString(); break; } var currentName = Nexus.LookUpAddress(source.Address); if (currentName == AccountContract.ANONYMOUS) { var lookup = Nexus.LookUpName(randomName); if (lookup == Address.Null) { GenerateAccountRegistration(source, randomName); } } } break; } // normal transfer default: { var temp = _rnd.Next() % 5; Address targetAddress; if ((_keys.Count < 2 || temp == 0) && _keys.Count < 2000) { var key = KeyPair.Generate(); _keys.Add(key); targetAddress = key.Address; } else { targetAddress = _keys[_rnd.Next() % _keys.Count].Address; } if (source.Address != targetAddress) { var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, Nexus.FuelTokenDecimals - 1); var tokenBalance = sourceChain.GetTokenBalance(token, source.Address); var fuelBalance = sourceChain.GetTokenBalance(Nexus.FuelToken, source.Address); var expectedTotal = total; if (token == Nexus.FuelToken) { expectedTotal += fee; } if (tokenBalance > expectedTotal && fuelBalance > fee) { GenerateTransfer(source, targetAddress, sourceChain, token, total); //Console.WriteLine(source.Address + " => " + targetAddress + " " + TokenUtils.ToDecimal( total, token.Decimals) + " " + token.Symbol); } } break; } } } EndBlock(mempool); }
public IEnumerable <Block> EndBlock(Mempool mempool = null) { if (!blockOpen) { throw new Exception("Simulator block not open"); } usedAddresses.Clear(); blockOpen = false; var blocks = new List <Block>(); var protocol = (uint)Nexus.GetGovernanceValue(Nexus.RootStorage, Nexus.NexusProtocolVersionTag); if (txChainMap.Count > 0) { var chains = txChainMap.Values.Distinct(); foreach (var chain in chains) { var hashes = txChainMap.Where((p) => p.Value == chain).Select(x => x.Key); if (hashes.Any()) { var txs = new List <Transaction>(); foreach (var hash in hashes) { txs.Add(txHashMap[hash]); } var lastBlockHash = chain.GetLastBlockHash(); var lastBlock = chain.GetBlockByHash(lastBlockHash); BigInteger nextHeight = lastBlock != null ? lastBlock.Height + 1 : Chain.InitialHeight; var prevHash = lastBlock != null ? lastBlock.Hash : Hash.Null; var block = new Block(nextHeight, chain.Address, CurrentTime, hashes, prevHash, protocol, this.blockValidator.Address, System.Text.Encoding.UTF8.GetBytes("SIM")); bool submitted; string reason = "unknown"; if (mempool != null) { submitted = true; foreach (var tx in txs) { try { mempool.Submit(tx); } catch (Exception e) { reason = e.Message; submitted = false; break; } } } else { try { var changeSet = chain.ProcessBlock(block, transactions, MinimumFee); block.Sign(this.blockValidator); chain.AddBlock(block, txs, MinimumFee, changeSet); submitted = true; } catch (Exception e) { reason = e.Message; submitted = false; } } if (submitted) { blocks.Add(block); CurrentTime += blockTimeSkip; Logger.Message($"End block #{step} @ {chain.Name} chain: {block.Hash}"); } else { throw new ChainException($"add block @ {chain.Name} failed, reason: {reason}"); } } } return(blocks); } return(Enumerable.Empty <Block>()); }
public CLI(string[] args) { var culture = new CultureInfo("en-US"); Thread.CurrentThread.CurrentCulture = culture; CultureInfo.DefaultThreadCurrentCulture = culture; var seeds = new List <string>(); var settings = new Arguments(args); var useGUI = settings.GetBool("gui.enabled", true); if (useGUI) { gui = new ConsoleGUI(); logger = gui; } else { gui = null; logger = new ConsoleLogger(); } string mode = settings.GetString("node.mode", "default"); restartTime = settings.GetInt("node.reboot", 0); showWebLogs = settings.GetBool("web.log", false); bool apiLog = settings.GetBool("api.log", true); string apiProxyURL = settings.GetString("api.proxy", ""); if (string.IsNullOrEmpty(apiProxyURL)) { apiProxyURL = null; } bool hasSync = settings.GetBool("sync.enabled", true); bool hasMempool = settings.GetBool("mempool.enabled", true); bool hasEvents = settings.GetBool("events.enabled", true); bool hasRelay = settings.GetBool("relay.enabled", true); bool hasArchive = settings.GetBool("archive.enabled", true); bool hasRPC = settings.GetBool("rpc.enabled", false); bool hasREST = settings.GetBool("rest.enabled", false); var nexusName = settings.GetString("nexus.name", "simnet"); string profilePath = settings.GetString("mempool.profile", ""); if (string.IsNullOrEmpty(profilePath)) { profilePath = null; } bool isValidator = false; switch (mode) { case "sender": { string host = settings.GetString("sender.host"); int threadCount = settings.GetInt("sender.threads", 8); int addressesPerSender = settings.GetInt("sender.addressCount", 100); string wif = settings.GetString("node.wif"); RunSender(wif, nexusName, host, threadCount, addressesPerSender); Console.WriteLine("Sender finished operations."); return; } case "validator": isValidator = true; break; case "default": break; default: { logger.Error("Unknown mode: " + mode); return; } } int port = settings.GetInt("node.port", 7073); var defaultStoragePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Storage"; var defaultOraclePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Oracle"; var storagePath = FixPath(settings.GetString("storage.path", defaultStoragePath)); var oraclePath = FixPath(settings.GetString("storage.oracle", defaultOraclePath)); var storageBackend = settings.GetString("storage.backend", "file"); logger.Message("Storage backend: " + storageBackend); var storageFix = settings.GetBool("storage.fix", false); // TODO remove this later if (storageFix) { if (Directory.Exists(storagePath)) { logger.Warning("Storage fix enabled... Cleaning up all storage..."); var di = new DirectoryInfo(storagePath); foreach (FileInfo file in di.EnumerateFiles()) { file.Delete(); } } } logger.Message("Storage path: " + storagePath); logger.Message("Oracle path: " + oraclePath); switch (storageBackend) { case "file": nexus = new Nexus(logger, (name) => new BasicDiskStore(storagePath + name + ".csv"), (n) => new SpookOracle(this, n, oraclePath) ); break; case "db": nexus = new Nexus(logger, (name) => new DBPartition(storagePath + name), (n) => new SpookOracle(this, n, oraclePath) ); break; default: throw new Exception("Backend has to be set to either \"db\" or \"file\""); } running = true; // mempool setup int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime); int minimumFee; try { minimumFee = settings.GetInt("mempool.fee", 100000); if (minimumFee < 1) { logger.Error("Invalid mempool fee value. Expected a positive value."); } } catch (Exception e) { logger.Error("Invalid mempool fee value. Expected something in fixed point format."); return; } int minimumPow; try { minimumPow = settings.GetInt("mempool.pow", 0); int maxPow = 5; if (minimumPow < 0 || minimumPow > maxPow) { logger.Error($"Invalid mempool pow value. Expected a value between 0 and {maxPow}."); } } catch (Exception e) { logger.Error("Invalid mempool fee value. Expected something in fixed point format."); return; } if (apiProxyURL != null) { hasMempool = false; isValidator = false; hasSync = false; hasEvents = false; hasRelay = false; hasArchive = false; if (!hasRPC && !hasREST) { logger.Error("API proxy must have REST or RPC enabled."); return; } } if (hasMempool) { this.mempool = new Mempool(nexus, blockTime, minimumFee, System.Text.Encoding.UTF8.GetBytes(Identifier), 0, logger, profilePath); var mempoolLogging = settings.GetBool("mempool.log", true); if (mempoolLogging) { mempool.OnTransactionFailed += Mempool_OnTransactionFailed; mempool.OnTransactionAdded += (hash) => logger.Message($"Received transaction {hash}"); mempool.OnTransactionCommitted += (hash) => logger.Message($"Commited transaction {hash}"); mempool.OnTransactionDiscarded += (hash) => logger.Message($"Discarded transaction {hash}"); } mempool.Start(ThreadPriority.AboveNormal); } else { this.mempool = null; } if (!isValidator && !hasSync && apiProxyURL == null) { logger.Warning("Non-validator nodes require sync feature to be enabled, auto enabled now"); hasSync = true; } PeerCaps caps = PeerCaps.None; if (hasSync) { caps |= PeerCaps.Sync; } if (hasMempool) { caps |= PeerCaps.Mempool; } if (hasEvents) { caps |= PeerCaps.Events; } if (hasRelay) { caps |= PeerCaps.Relay; } if (hasArchive) { caps |= PeerCaps.Archive; } if (hasRPC) { caps |= PeerCaps.RPC; } if (hasREST) { caps |= PeerCaps.REST; } var possibleCaps = Enum.GetValues(typeof(PeerCaps)).Cast <PeerCaps>().ToArray(); foreach (var cap in possibleCaps) { if (cap != PeerCaps.None && caps.HasFlag(cap)) { logger.Message("Feature enabled: " + cap); } } PhantasmaKeys node_keys = null; bool bootstrap = false; if (hasSync) { string wif = settings.GetString("node.wif"); node_keys = PhantasmaKeys.FromWIF(wif); WalletModule.Keys = PhantasmaKeys.FromWIF(wif); try { if (this.mempool != null) { this.mempool.SetKeys(node_keys); } this.node = new Node("Spook v" + SpookVersion, nexus, mempool, node_keys, port, caps, seeds, logger); } catch (Exception e) { logger.Error(e.Message); return; } if (!nexus.HasGenesis) { if (isValidator) { if (settings.GetBool("nexus.bootstrap")) { if (!ValidationUtils.IsValidIdentifier(nexusName)) { logger.Error("Invalid nexus name: " + nexusName); this.Terminate(); return; } logger.Debug($"Boostraping {nexusName} nexus using {node_keys.Address}..."); var genesisTimestamp = new Timestamp(settings.GetUInt("genesis.timestamp", Timestamp.Now.Value)); bootstrap = true; if (!nexus.CreateGenesisBlock(nexusName, node_keys, genesisTimestamp)) { throw new ChainException("Genesis block failure"); } logger.Debug("Genesis block created: " + nexus.GetGenesisHash(nexus.RootStorage)); } else { logger.Error("No Nexus found."); this.Terminate(); } } } else { var genesisAddress = nexus.GetGenesisAddress(nexus.RootStorage); if (isValidator && node_keys.Address != genesisAddress) { logger.Error("Specified node key does not match genesis address " + genesisAddress.Text); return; } else { logger.Success("Loaded Nexus with genesis " + nexus.GetGenesisHash(nexus.RootStorage)); //seeds.Add("127.0.0.1:7073"); } } } else { this.node = null; } if (mempool != null) { if (isValidator) { this.mempool.SetKeys(node_keys); } else { this.mempool.SubmissionCallback = (tx, chain) => { logger.Message($"Relaying tx {tx.Hash} to other node"); //this.node. }; } } var useAPICache = settings.GetBool("api.cache", true); if (apiProxyURL != null) { useAPICache = true; } logger.Message($"API cache is {(useAPICache ? "enabled" : "disabled")}."); nexusApi = new NexusAPI(nexus, useAPICache, apiLog ? logger : null); nexusApi.Mempool = mempool; if (!string.IsNullOrEmpty(apiProxyURL)) { nexusApi.ProxyURL = apiProxyURL; logger.Message($"API will be acting as proxy for {apiProxyURL}"); } else { nexusApi.Node = node; } var readOnlyMode = settings.GetBool("readonly", false); if (apiProxyURL != null) { readOnlyMode = true; } if (readOnlyMode) { logger.Warning($"Node will be running in read-only mode."); nexusApi.acceptTransactions = false; } // RPC setup if (hasRPC) { rpcPort = settings.GetInt("rpc.port", 7077); logger.Message($"RPC server listening on port {rpcPort}..."); var rpcServer = new RPCServer(nexusApi, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text)); rpcServer.Start(ThreadPriority.AboveNormal); } else { rpcPort = 0; } // REST setup if (hasREST) { restPort = settings.GetInt("rest.port", 7078); logger.Message($"REST server listening on port {restPort}..."); var restServer = new RESTServer(nexusApi, "/api", restPort, (level, text) => WebLogMapper("rest", level, text)); restServer.Start(ThreadPriority.AboveNormal); } else { restPort = 0; } if (node != null) { var neoScanURL = settings.GetString("neoscan.url", "https://api.neoscan.io"); var rpcList = settings.GetString("neo.rpc", "http://seed6.ngd.network:10332,http://seed.neoeconomy.io:10332"); var neoRpcURLs = rpcList.Split(','); this.neoAPI = new Neo.Core.RemoteRPCNode(neoScanURL, neoRpcURLs); this.neoAPI.SetLogger((s) => logger.Message(s)); this.neoScanAPI = new NeoScanAPI(neoScanURL, logger, nexus, node_keys); cryptoCompareAPIKey = settings.GetString("cryptocompare.apikey", ""); if (!string.IsNullOrEmpty(cryptoCompareAPIKey)) { logger.Message($"CryptoCompare API enabled..."); } node.Start(); } if (gui != null) { int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds if (settings.GetBool("plugin.tps", false)) { RegisterPlugin(new TPSPlugin(logger, pluginPeriod)); } if (settings.GetBool("plugin.ram", false)) { RegisterPlugin(new RAMPlugin(logger, pluginPeriod)); } if (settings.GetBool("plugin.mempool", false)) { RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod)); } } Console.CancelKeyPress += delegate { Terminate(); }; useSimulator = settings.GetBool("simulator.enabled", false); var dispatcher = new CommandDispatcher(); SetupCommands(dispatcher); if (settings.GetBool("swaps.enabled")) { var tokenSwapper = new TokenSwapper(node_keys, nexusApi, neoScanAPI, neoAPI, minimumFee, logger, settings); nexusApi.TokenSwapper = tokenSwapper; new Thread(() => { logger.Message("Running token swapping service..."); while (running) { Thread.Sleep(5000); if (nodeReady) { tokenSwapper.Update(); } } }).Start(); } if (useSimulator && bootstrap) { new Thread(() => { logger.Message("Initializing simulator..."); simulator = new NexusSimulator(this.nexus, node_keys, 1234); simulator.MinimumFee = minimumFee; /* * logger.Message("Bootstrapping validators"); * simulator.BeginBlock(); * for (int i = 1; i < validatorWIFs.Length; i++) * { * simulator.GenerateTransfer(node_keys, Address.FromWIF(validatorWIFs[i]), this.nexus.RootChain, DomainSettings.StakingTokenSymbol, UnitConversion.ToBigInteger(50000, DomainSettings.StakingTokenDecimals)); * } * simulator.EndBlock();*/ string[] dapps = settings.GetString("dapps", "").Split(','); DappServer.InitDapps(nexus, simulator, node_keys, dapps, minimumFee, logger); bool genBlocks = settings.GetBool("simulator.blocks", false); if (genBlocks) { int blockNumber = 0; while (running) { Thread.Sleep(5000); blockNumber++; logger.Message("Generating sim block #" + blockNumber); try { simulator.CurrentTime = DateTime.UtcNow; simulator.GenerateRandomBlock(); } catch (Exception e) { logger.Error("Fatal error: " + e.ToString()); Environment.Exit(-1); } } } MakeReady(dispatcher); }).Start(); } else { MakeReady(dispatcher); } this.Run(); }
public CLI(string[] args) { var seeds = new List <string>(); var settings = new Arguments(args); var useGUI = settings.GetBool("gui.enabled", true); if (useGUI) { gui = new ConsoleGUI(); logger = gui; } else { gui = null; logger = new ConsoleLogger(); } string mode = settings.GetString("node.mode", "validator"); bool hasRPC = settings.GetBool("rpc.enabled", false); bool hasREST = settings.GetBool("rest.enabled", false); string wif = settings.GetString("node.wif"); var nexusName = settings.GetString("nexus.name", "simnet"); var genesisAddress = Address.FromText(settings.GetString("nexus.genesis", KeyPair.FromWIF(validatorWIFs[0]).Address.Text)); switch (mode) { case "sender": string host = settings.GetString("sender.host"); int threadCount = settings.GetInt("sender.threads", 8); int addressesPerSender = settings.GetInt("sender.addressCount", 100); RunSender(wif, host, threadCount, addressesPerSender); Console.WriteLine("Sender finished operations."); return; case "validator": break; default: { logger.Error("Unknown mode: " + mode); return; } } int defaultPort = 0; for (int i = 0; i < validatorWIFs.Length; i++) { if (validatorWIFs[i] == wif) { defaultPort = (7073 + i); } } if (defaultPort == 0) { defaultPort = (7073 + validatorWIFs.Length); } int port = settings.GetInt("node.port", defaultPort); var node_keys = KeyPair.FromWIF(wif); // TODO increase this later int cacheSize = 32; nexus = new Nexus(logger); if (wif != validatorWIFs[0]) { seeds.Add("127.0.0.1:7073"); } // TODO this should be later optional to enable nexus.AddPlugin(new ChainAddressesPlugin()); nexus.AddPlugin(new TokenTransactionsPlugin()); nexus.AddPlugin(new AddressTransactionsPlugin()); nexus.AddPlugin(new UnclaimedTransactionsPlugin()); /*if (simulator != null) * { * for (int i = 0; i < 100; i++) * { * simulator.GenerateRandomBlock(); * } * }*/ running = true; // mempool setup int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime); this.mempool = new Mempool(node_keys, nexus, blockTime); mempool.Start(ThreadPriority.AboveNormal); mempool.OnTransactionFailed += Mempool_OnTransactionFailed; api = new NexusAPI(nexus, mempool); // RPC setup if (hasRPC) { int rpcPort = settings.GetInt("rpc.port", 7077); logger.Message($"RPC server listening on port {rpcPort}..."); var rpcServer = new RPCServer(api, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text)); rpcServer.Start(ThreadPriority.AboveNormal); } // REST setup if (hasREST) { int restPort = settings.GetInt("rest.port", 7078); logger.Message($"REST server listening on port {restPort}..."); var restServer = new RESTServer(api, "/api", restPort, (level, text) => WebLogMapper("rest", level, text)); restServer.Start(ThreadPriority.AboveNormal); } /*if (simulator != null && settings.GetBool("simulator", false)) * { * new Thread(() => * { * Thread.CurrentThread.IsBackground = true; * while (running) * { * Thread.Sleep(Mempool.MinimumBlockTime + 1000); * simulator.CurrentTime = Timestamp.Now; * simulator.GenerateRandomBlock(mempool); * } * }).Start(); * }*/ // node setup this.node = new Node(nexus, mempool, node_keys, port, seeds, logger); node.Start(); int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds RegisterPlugin(new TPSPlugin(logger, pluginPeriod)); RegisterPlugin(new RAMPlugin(logger, pluginPeriod)); RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod)); Console.CancelKeyPress += delegate { Terminate(); }; logger.Success("Node is ready"); var dispatcher = new CommandDispatcher(); SetupCommands(dispatcher); if (gui != null) { gui.MakeReady(dispatcher); } this.Run(); }
public IEnumerable <Block> EndBlock(Mempool mempool = null) { if (!blockOpen) { throw new Exception("Simulator block not open"); } usedAddresses.Clear(); blockOpen = false; var blocks = new List <Block>(); var protocol = (uint)Nexus.GetGovernanceValue(Nexus.RootStorage, Nexus.NexusProtocolVersionTag); if (txChainMap.Count > 0) { var chains = txChainMap.Values.Distinct(); foreach (var chain in chains) { var hashes = txChainMap.Where((p) => p.Value == chain).Select(x => x.Key); if (hashes.Any()) { var txs = new List <Transaction>(); foreach (var hash in hashes) { txs.Add(txHashMap[hash]); } var lastBlockHash = chain.GetLastBlockHash(); var lastBlock = chain.GetBlockByHash(lastBlockHash); BigInteger nextHeight = lastBlock != null ? lastBlock.Height + 1 : Chain.InitialHeight; var prevHash = lastBlock != null ? lastBlock.Hash : Hash.Null; var block = new Block(nextHeight, chain.Address, CurrentTime, hashes, prevHash, protocol); bool submitted; string reason = "unknown"; if (mempool != null) { submitted = true; foreach (var tx in txs) { try { mempool.Submit(tx); } catch (Exception e) { reason = e.Message; submitted = false; break; } } } else { try { chain.BakeBlock(ref block, ref txs, MinimumFee, blockValidator, CurrentTime); chain.AddBlock(block, txs, MinimumFee); submitted = true; } catch (Exception e) { reason = e.Message; submitted = false; } } if (submitted) { blocks.Add(block); CurrentTime += blockTimeSkip; // add the finished block hash to each pending side chain tx if (_pendingEntries.Count > 0) { foreach (var entry in _pendingEntries.Values) { if (entry.sourceChain != chain) { continue; } var pendingBlock = new SideChainPendingBlock() { sourceChain = entry.sourceChain, destChain = entry.destChain, hash = block.Hash, tokenSymbol = entry.tokenSymbol }; _pendingBlocks.Add(pendingBlock); Logger.Debug($"...Sending {entry.sourceChain.Name}=>{entry.destChain.Name}: {block.Hash}"); } } Logger.Message($"End block #{step} @ {chain.Name} chain: {block.Hash}"); } else { throw new ChainException($"add block @ {chain.Name} failed, reason: {reason}"); } } } _pendingEntries.Clear(); return(blocks); } return(Enumerable.Empty <Block>()); }