public bool SyncBlock(uint blockHeight) { TaskSession session = GetSyncSession(blockHeight, false); if (session == null) { return(false); } UInt256 hash = blockchain.GetBlockHash(blockHeight); if (hash == null) { return(false); } if (!globalTasks.Add(hash)) { return(true); } AddSyncBlockTask(hash, blockHeight, session); session.RemoteNode.Tell(Message.Create(MessageType.GetData, InvPayload.Create(InventoryType.Block, hash))); session.RemoteNode.Tell(RemoteNode.NewCounterMessage(RemoteNode.CounterType.Request, InventoryType.Block)); syncingBlockHeight = blockHeight; Log($"SyncBlock:{blockHeight}, nodeId:{session.Version.NodeId}", LogLevel.Debug); return(true); }
private void CheckSyncBlockTimeout() { DateTime now = DateTime.UtcNow; SyncBlockTask[] timeoutTasks = syncBlockTasks.Values.SelectMany(p => p.Where(q => now >= q.ExpiryTime)).ToArray(); foreach (SyncBlockTask task in timeoutTasks) { task.Session.Timeout++; task.Session.RemoteNode.Tell(RemoteNode.NewCounterMessage(RemoteNode.CounterType.Timeout, InventoryType.Block)); Log($"SyncBlock timeout:{task.BlockHeight}, nodeId:{task.Session.Version.NodeId}"); if (task.BlockHeight <= blockchain.Height) { RemoveSyncBlockTask(task); } else { TaskSession session = GetSyncSession(task.BlockHeight, false); if (session != null) { RestartSyncBlockTask(task, session); session.RemoteNode.Tell(Message.Create(MessageType.GetData, InvPayload.Create(InventoryType.Block, task.Hash))); session.RemoteNode.Tell(RemoteNode.NewCounterMessage(RemoteNode.CounterType.Request, InventoryType.Block)); } else { RemoveSyncBlockTask(task); } } } }
private async Task OnGetBlocksMessageReceivedAsync(GetBlocksPayload payload) { if (!localNode.ServiceEnabled) { return; } if (Blockchain.Default == null) { return; } UInt256 hash = payload.HashStart.Select(p => new { Hash = p, Height = Blockchain.Default.GetBlockHeight(p) }).Where(p => p.Height >= 0).OrderBy(p => p.Height).Select(p => p.Hash).FirstOrDefault(); if (hash == null || hash == payload.HashStop) { return; } List <UInt256> hashes = new List <UInt256>(); do { hash = Blockchain.Default.GetNextBlockHash(hash); if (hash == null) { break; } hashes.Add(hash); } while (hash != payload.HashStop && hashes.Count < 500); await SendMessageAsync("inv", InvPayload.Create(InventoryType.MSG_BLOCK, hashes.ToArray())); }
private void OnInvMessageReceived(InvPayload payload) { if (payload.Type != InventoryType.TX && payload.Type != InventoryType.Block && payload.Type != InventoryType.Consensus) { return; } UInt256[] hashes = payload.Hashes.Distinct().ToArray(); lock (LocalNode.KnownHashes) { hashes = hashes.Where(p => !LocalNode.KnownHashes.Contains(p)).ToArray(); } if (hashes.Length == 0) { return; } lock (missions_global) { if (localNode.GlobalMissionsEnabled) { hashes = hashes.Where(p => !missions_global.Contains(p)).ToArray(); } foreach (UInt256 hash in hashes) { missions_global.Add(hash); missions.Add(hash); } } if (hashes.Length == 0) { return; } EnqueueMessage("getdata", InvPayload.Create(payload.Type, hashes)); }
private void OnInvMessageReceived(InvPayload payload) { UInt256[] hashes = payload.Hashes.Where(p => knownHashes.Add(p)).ToArray(); if (hashes.Length == 0) { return; } switch (payload.Type) { case InventoryType.Block: using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot()) hashes = hashes.Where(p => !snapshot.ContainsBlock(p)).ToArray(); break; case InventoryType.TX: using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot()) hashes = hashes.Where(p => !snapshot.ContainsTransaction(p)).ToArray(); break; } if (hashes.Length == 0) { return; } system.TaskManager.Tell(new TaskManager.NewTasks { Payload = InvPayload.Create(payload.Type, hashes) }, Context.Parent); }
private bool OnBroadcastCommand(string[] args) { string command = args[1].ToLower(); ISerializable payload = null; switch (command) { case "addr": payload = AddrPayload.Create(NetworkAddressWithTime.Create(new IPEndPoint(IPAddress.Parse(args[2]), ushort.Parse(args[3])), NetworkAddressWithTime.NODE_NETWORK, DateTime.UtcNow.ToTimestamp())); break; case "block": if (args[2].Length == 64 || args[2].Length == 66) { payload = Blockchain.Default.GetBlock(UInt256.Parse(args[2])); } else { payload = Blockchain.Default.GetBlock(uint.Parse(args[2])); } break; case "getblocks": case "getheaders": payload = GetBlocksPayload.Create(UInt256.Parse(args[2])); break; case "getdata": case "inv": payload = InvPayload.Create(Enum.Parse <InventoryType>(args[2], true), args.Skip(3).Select(p => UInt256.Parse(p)).ToArray()); break; case "tx": payload = LocalNode.GetTransaction(UInt256.Parse(args[2])); if (payload == null) { payload = Blockchain.Default.GetTransaction(UInt256.Parse(args[2])); } break; case "alert": case "consensus": case "filteradd": case "filterload": case "headers": case "merkleblock": case "ping": case "pong": case "reject": case "verack": case "version": Console.WriteLine($"Command \"{command}\" is not supported."); return(true); } foreach (RemoteNode node in LocalNode.GetRemoteNodes()) { node.EnqueueMessage(command, payload); } return(true); }
private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest message) { TR.Enter(); Log($"{nameof(OnPrepareRequestReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} tx={message.TransactionHashes.Length}"); if (!context.State.HasFlag(ConsensusState.Backup) || context.State.HasFlag(ConsensusState.RequestReceived)) { TR.Exit(); return; } if (payload.ValidatorIndex != context.PrimaryIndex) { return; } if (payload.Timestamp <= Blockchain.Default.GetHeader(context.PrevHash).Timestamp || payload.Timestamp > DateTime.Now.AddMinutes(10).ToTimestamp()) { Log($"Timestamp incorrect: {payload.Timestamp}"); TR.Exit(); return; } context.State |= ConsensusState.RequestReceived; context.Timestamp = payload.Timestamp; context.Nonce = message.Nonce; context.NextConsensus = message.NextConsensus; context.TransactionHashes = message.TransactionHashes; context.Transactions = new Dictionary <UInt256, Transaction>(); if (!Crypto.Default.VerifySignature(context.MakeHeader().GetHashData(), message.Signature, context.Validators[payload.ValidatorIndex].EncodePoint(false))) { TR.Exit(); return; } context.Signatures = new byte[context.Validators.Length][]; context.Signatures[payload.ValidatorIndex] = message.Signature; Dictionary <UInt256, Transaction> mempool = LocalNode.GetMemoryPool().ToDictionary(p => p.Hash); foreach (UInt256 hash in context.TransactionHashes.Skip(1)) { if (mempool.TryGetValue(hash, out Transaction tx)) { if (!AddTransaction(tx, false)) { TR.Exit(); return; } } } if (!AddTransaction(message.MinerTransaction, true)) { TR.Exit(); return; } if (context.Transactions.Count < context.TransactionHashes.Length) { UInt256[] hashes = context.TransactionHashes.Where(i => !context.Transactions.ContainsKey(i)).ToArray(); LocalNode.AllowHashes(hashes); InvPayload msg = InvPayload.Create(InventoryType.TX, hashes); foreach (RemoteNode node in localNode.GetRemoteNodes()) { node.EnqueueMessage("getdata", msg); } } TR.Exit(); }
private void OnInvMessageReceived(InvPayload payload) { InventoryVector[] vectors = payload.Inventories.Distinct().Where(p => Enum.IsDefined(typeof(InventoryType), p.Type)).ToArray(); lock (LocalNode.KnownHashes) { vectors = vectors.Where(p => !LocalNode.KnownHashes.Contains(p.Hash)).ToArray(); } if (vectors.Length == 0) { return; } lock (missions_global) { if (localNode.GlobalMissionsEnabled) { vectors = vectors.Where(p => !missions_global.Contains(p.Hash)).ToArray(); } foreach (InventoryVector vector in vectors) { missions_global.Add(vector.Hash); missions.Add(vector.Hash); } } if (vectors.Length == 0) { return; } EnqueueMessage("getdata", InvPayload.Create(vectors)); }
private void OnGetBlocksMessageReceived(GetBlocksPayload payload) { if (!localNode.ServiceEnabled) { return; } if (Blockchain.Default == null) { return; } UInt256 hash = payload.HashStart.Select(p => Blockchain.Default.GetHeader(p)).Where(p => p != null).OrderBy(p => p.Index).Select(p => p.Hash).FirstOrDefault(); if (hash == null || hash == payload.HashStop) { return; } List <UInt256> hashes = new List <UInt256>(); do { hash = Blockchain.Default.GetNextBlockHash(hash); if (hash == null) { break; } hashes.Add(hash); } while (hash != payload.HashStop && hashes.Count < 500); EnqueueMessage("inv", InvPayload.Create(InventoryType.Block, hashes.ToArray())); }
private void RequestInventoryData(InventoryType type, UInt256[] hashes, IActorRef sender) { if (hashes.Length == 0) { return; } if (hashes.Length == 1) { sender.Tell(Message.Create(MessageType.GetData, InvPayload.Create(type, hashes[0]))); } else { string cmd; if (type == InventoryType.Block) { cmd = MessageType.GetBlk; } else if (type == InventoryType.TX) { cmd = MessageType.GetTxn; } else { return; } foreach (InvPayload group in InvPayload.CreateGroup(type, hashes)) { sender.Tell(Message.Create(cmd, group)); } } Sender.Tell(RemoteNode.NewCounterMessage(RemoteNode.CounterType.Request, type, hashes.Length)); }
private void OnGetBlocksMessageReceived(GetBlocksPayload payload) { UInt256 hash = payload.HashStart; int count = payload.Count <0 || payload.Count> InvPayload.MaxHashesCount ? InvPayload.MaxHashesCount : payload.Count; TrimmedBlock state = Blockchain.Singleton.Store.GetBlocks().TryGet(hash); if (state == null) { return; } List <UInt256> hashes = new List <UInt256>(); for (uint i = 1; i <= count; i++) { uint index = state.Index + i; if (index > Blockchain.Singleton.Height) { break; } hash = Blockchain.Singleton.GetBlockHash(index); if (hash == null) { break; } hashes.Add(hash); } if (hashes.Count == 0) { return; } Context.Parent.Tell(Message.Create(MessageCommand.Inv, InvPayload.Create(InventoryType.Block, hashes.ToArray()))); }
public void Size_Get() { var test = InvPayload.Create(InventoryType.TX, UInt256.Zero); test.Size.Should().Be(34); test = InvPayload.Create(InventoryType.TX, UInt256.Zero, UInt256.Parse("01ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00a4")); test.Size.Should().Be(66); }
public void DeserializeAndSerialize() { var test = InvPayload.Create(InventoryType.TX, UInt256.Zero, UInt256.Parse("01ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00a4")); var clone = test.ToArray().AsSerializable <InvPayload>(); Assert.AreEqual(test.Type, clone.Type); CollectionAssert.AreEqual(test.Hashes, clone.Hashes); Assert.ThrowsException <FormatException>(() => InvPayload.Create((InventoryType)0xff, UInt256.Zero).ToArray().AsSerializable <InvPayload>()); }
private void InitializeConsensus(byte view_number) { lock (context) { if (view_number == 0) { context.Reset(wallet); } else { context.ChangeView(view_number); } if (context.MyIndex < 0) { return; } Log($"initialize: height={context.BlockIndex} view={view_number} index={context.MyIndex} role={(context.MyIndex == context.PrimaryIndex ? ConsensusState.Primary : ConsensusState.Backup)}"); if (context.MyIndex == context.PrimaryIndex) { context.State |= ConsensusState.Primary; if (!context.State.HasFlag(ConsensusState.SignatureSent)) { FillContext(); } if (context.TransactionHashes.Length > 1) { InvPayload invPayload = InvPayload.Create(InventoryType.TX, context.TransactionHashes.Skip(1).ToArray()); foreach (RemoteNode node in localNode.GetRemoteNodes()) { node.EnqueueMessage("inv", invPayload); } } timer_height = context.BlockIndex; timer_view = view_number; // 议长发起共识时间控制 TimeSpan span = DateTime.Now - block_received_time; if (span >= Blockchain.TimePerBlock) { timer.Change(0, Timeout.Infinite);// 间隔时间大于预订时间则立即发起共识 } else { timer.Change(Blockchain.TimePerBlock - span, Timeout.InfiniteTimeSpan);// 定时执行 } } else { context.State = ConsensusState.Backup; timer_height = context.BlockIndex; timer_view = view_number; // 议员超时控制 t * 2 ^ (view_number + 1) timer.Change(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (view_number + 1)), Timeout.InfiniteTimeSpan); } } }
private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest message) { Log($"{nameof(OnPrepareRequestReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} tx={message.TransactionHashes.Length}"); if (!context.State.HasFlag(ConsensusState.Backup) || context.State.HasFlag(ConsensusState.RequestReceived)) { return; } if (payload.ValidatorIndex != context.PrimaryIndex) { return; } if (payload.Timestamp <= context.Snapshot.GetHeader(context.PrevHash).Timestamp || payload.Timestamp > DateTime.UtcNow.AddMinutes(10).ToTimestamp()) { Log($"Timestamp incorrect: {payload.Timestamp}", LogLevel.Warning); return; } context.State |= ConsensusState.RequestReceived; context.Timestamp = payload.Timestamp; context.Nonce = message.Nonce; context.NextConsensus = message.NextConsensus; context.TransactionHashes = message.TransactionHashes; context.Transactions = new Dictionary <UInt256, Transaction>(); if (!Crypto.Default.VerifySignature(context.MakeHeader().GetHashData(), message.Signature, context.Validators[payload.ValidatorIndex].EncodePoint(false))) { return; } context.Signatures = new byte[context.Validators.Length][]; context.Signatures[payload.ValidatorIndex] = message.Signature; Dictionary <UInt256, Transaction> mempool = blockchain.GetMemoryPool().ToDictionary(p => p.Hash); foreach (UInt256 hash in context.TransactionHashes.Skip(1)) { if (mempool.TryGetValue(hash, out Transaction tx)) { if (!AddTransaction(tx, false)) { return; } } } message.MinerTransaction.ChainHash = chainHash; if (!AddTransaction(message.MinerTransaction, true)) { return; } if (context.Transactions.Count < context.TransactionHashes.Length) { UInt256[] hashes = context.TransactionHashes.Where(i => !context.Transactions.ContainsKey(i)).ToArray(); system.TaskManager.Tell(new TaskManager.RestartTasks { Payload = InvPayload.Create(InventoryType.TX, hashes) }); } }
private void OnRelay(IInventory inventory) { if (!IsFullNode) { return; } //if (inventory.InventoryType == InventoryType.TX) //{ // if (bloom_filter != null && !bloom_filter.Test((Transaction)inventory)) // return; //} EnqueueMessage(MessageCommand.Inv, InvPayload.Create(inventory.InventoryType, inventory.Hash)); }
private void OnInvMessageReceived(InvPayload payload) { TR.Enter(); if (payload.Type != InventoryType.TX && payload.Type != InventoryType.Block && payload.Type != InventoryType.Consensus) { TR.Exit(); return; } HashSet <UInt256> hashes = new HashSet <UInt256>(payload.Hashes); lock (LocalNode.KnownHashes) { hashes.RemoveWhere(p => LocalNode.KnownHashes.TryGetValue(p, out DateTime time) && time + LocalNode.HashesExpiration >= DateTime.UtcNow); } if (hashes.Count == 0) { TR.Exit(); return; } lock (missions_global) { lock (missions) { if (localNode.GlobalMissionsEnabled) { hashes.RemoveWhere(p => missions_global.TryGetValue(p, out DateTime time) && time + MissionExpiration >= DateTime.UtcNow); } if (hashes.Count > 0) { if (missions.Count == 0) { mission_start = DateTime.Now; } foreach (UInt256 hash in hashes) { if (!missions_global.ContainsKey(hash)) { missions_global.Add(hash, DateTime.UtcNow); } } missions.UnionWith(hashes); } } } if (hashes.Count == 0) { TR.Exit(); return; } EnqueueMessage("getdata", InvPayload.Create(payload.Type, hashes.ToArray())); TR.Exit(); }
private void OnRelay(IInventory inventory) { if (Version?.Services.HasFlag(VersionServices.AcceptRelay) != true) { return; } if (inventory.InventoryType == InventoryType.TX) { if (bloom_filter != null && !bloom_filter.Test((Transaction)inventory)) { return; } } EnqueueMessage(MessageCommand.Inv, InvPayload.Create(inventory.InventoryType, inventory.Hash)); }
private void OnRelay(IInventory inventory) { if (Version?.Relay != true) { return; } if (inventory.InventoryType == InventoryType.TX) { if (bloom_filter != null && !bloom_filter.Test((Transaction)inventory)) { return; } } EnqueueMessage("inv", InvPayload.Create(inventory.InventoryType, inventory.Hash)); }
private bool OnBroadcastCommand(string[] args) { if (!Enum.TryParse(args[1], true, out MessageCommand command)) { Console.WriteLine($"Command \"{args[1]}\" is not supported."); return(true); } ISerializable payload = null; switch (command) { case MessageCommand.Addr: payload = AddrPayload.Create(NetworkAddressWithTime.Create(IPAddress.Parse(args[2]), DateTime.UtcNow.ToTimestamp(), new FullNodeCapability(), new ServerCapability(NodeCapabilityType.TcpServer, ushort.Parse(args[3])))); break; case MessageCommand.Block: if (args[2].Length == 64 || args[2].Length == 66) { payload = Blockchain.Singleton.GetBlock(UInt256.Parse(args[2])); } else { payload = Blockchain.Singleton.Store.GetBlock(uint.Parse(args[2])); } break; case MessageCommand.GetBlocks: case MessageCommand.GetHeaders: payload = GetBlocksPayload.Create(UInt256.Parse(args[2])); break; case MessageCommand.GetData: case MessageCommand.Inv: payload = InvPayload.Create(Enum.Parse <InventoryType>(args[2], true), args.Skip(3).Select(UInt256.Parse).ToArray()); break; case MessageCommand.Transaction: payload = Blockchain.Singleton.GetTransaction(UInt256.Parse(args[2])); break; default: Console.WriteLine($"Command \"{command}\" is not supported."); return(true); } system.LocalNode.Tell(Message.Create(command, payload)); return(true); }
internal bool Relay(IInventory data) { if (Version?.Relay != true) { return(false); } if (data.InventoryType == InventoryType.TX) { BloomFilter filter = bloom_filter; if (filter != null && !TestFilter(filter, (Transaction)data)) { return(false); } } EnqueueMessage("inv", InvPayload.Create(data.InventoryType, data.Hash)); return(true); }
internal void Relay(IEnumerable <Transaction> transactions) { if (Version?.Relay != true) { return; } BloomFilter filter = bloom_filter; if (filter != null) { transactions = transactions.Where(p => TestFilter(filter, p)); } UInt256[] hashes = transactions.Select(p => p.Hash).ToArray(); if (hashes.Length == 0) { return; } EnqueueMessage("inv", InvPayload.Create(InventoryType.TX, hashes)); }
private void OnGetBlocksMessageReceived(Message msg) { GetBlocksPayload payload = msg.GetPayload <GetBlocksPayload>(); UInt256 hash = payload.HashStart[0]; if (hash == payload.HashStop) { return; } BlockState state = blockchain.Store.GetBlocks().TryGet(hash); if (state == null) { return; } List <UInt256> hashes = new List <UInt256>(); for (uint i = 1; i <= InvPayload.MaxHashesCount; i++) { uint index = state.TrimmedBlock.Index + i; if (index > blockchain.Height) { break; } hash = blockchain.GetBlockHash(index); if (hash == null) { break; } if (hash == payload.HashStop) { break; } hashes.Add(hash); } if (hashes.Count == 0) { return; } Context.Parent.Tell(Message.Create(MessageType.Inv, InvPayload.Create(InventoryType.Block, hashes.ToArray()))); blockchain.Log($"OnGetBlocks, blockIndex:{state.TrimmedBlock.Index}, count:{hashes.Count}, [{remoteNode.Remote.Address}]"); }
private bool OnBroadcastCommand(string[] args) { string command = args[1].ToLower(); ISerializable payload = null; switch (command) { case "addr": payload = AddrPayload.Create(NetworkAddressWithTime.Create(new IPEndPoint(IPAddress.Parse(args[2]), ushort.Parse(args[3])), NetworkAddressWithTime.NODE_NETWORK, DateTime.UtcNow.ToTimestamp())); break; case "block": if (args[2].Length == 64 || args[2].Length == 66) { payload = Blockchain.Singleton.GetBlock(UInt256.Parse(args[2])); } else { payload = Blockchain.Singleton.Store.GetBlock(uint.Parse(args[2])); } break; case "getblocks": case "getheaders": payload = GetBlocksPayload.Create(UInt256.Parse(args[2])); break; case "getdata": case "inv": payload = InvPayload.Create(Enum.Parse <InventoryType>(args[2], true), args.Skip(3).Select(UInt256.Parse).ToArray()); break; case "tx": payload = Blockchain.Singleton.GetTransaction(UInt256.Parse(args[2])); break; default: Console.WriteLine($"Command \"{command}\" is not supported."); return(true); } system.LocalNode.Tell(Message.Create(command, payload)); return(true); }
private void OnTimeout(object state) { lock (context) { if (timer_height != context.BlockIndex || timer_view != context.ViewNumber) { return; } Log($"timeout: height={timer_height} view={timer_view} state={context.State}"); if (context.State.HasFlag(ConsensusState.Primary) && !context.State.HasFlag(ConsensusState.RequestSent)) { Log($"send perpare request: height={timer_height} view={timer_view}"); context.State |= ConsensusState.RequestSent; if (!context.State.HasFlag(ConsensusState.SignatureSent)) { context.Timestamp = Math.Max(DateTime.Now.ToTimestamp(), Blockchain.Default.GetHeader(context.PrevHash).Timestamp + 1); context.Nonce = GetNonce(); List <Transaction> transactions = LocalNode.GetMemoryPool().Where(p => CheckPolicy(p)).ToList(); if (transactions.Count >= Settings.Default.MaxTransactionsPerBlock) { transactions = transactions.OrderByDescending(p => p.NetworkFee / p.Size).Take(Settings.Default.MaxTransactionsPerBlock - 1).ToList(); } transactions.Insert(0, CreateMinerTransaction(transactions, context.BlockIndex, context.Nonce)); context.TransactionHashes = transactions.Select(p => p.Hash).ToArray(); context.Transactions = transactions.ToDictionary(p => p.Hash); context.NextConsensus = Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(transactions).ToArray()); context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair); } InvPayload invPayload = InvPayload.Create(InventoryType.TX, context.TransactionHashes); foreach (RemoteNode node in localNode.GetRemoteNodes()) { node.EnqueueMessage("inv", invPayload); } SignAndRelay(context.MakePrepareRequest()); timer.Change(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (timer_view + 1)), Timeout.InfiniteTimeSpan); } else if ((context.State.HasFlag(ConsensusState.Primary) && context.State.HasFlag(ConsensusState.RequestSent)) || context.State.HasFlag(ConsensusState.Backup)) { RequestChangeView(); } } }
private void OnInvMessageReceived(InvPayload payload) { if (payload.Type != InventoryType.TX && payload.Type != InventoryType.Block && payload.Type != InventoryType.Consensus) { return; } UInt256[] hashes = payload.Hashes.Distinct().ToArray(); lock (LocalNode.KnownHashes) { hashes = hashes.Where(p => !LocalNode.KnownHashes.ContainsKey(p) || DateTime.UtcNow - LocalNode.KnownHashes[p] > LocalNode.HashesExpiration).ToArray(); } if (hashes.Length == 0) { return; } lock (missions_global) { lock (missions) { if (localNode.GlobalMissionsEnabled) { hashes = hashes.Where(p => !missions_global.Contains(p)).ToArray(); } if (hashes.Length > 0) { if (missions.Count == 0) { mission_start = DateTime.Now; } missions_global.UnionWith(hashes); missions.UnionWith(hashes); } } } if (hashes.Length == 0) { return; } EnqueueMessage("getdata", InvPayload.Create(payload.Type, hashes)); }
private void OnGetBlocksMessageReceived(GetBlocksPayload payload) { UInt256 hash = payload.HashStart[0]; if (hash == payload.HashStop) { return; } BlockState state = blockchain.Store.GetBlocks().TryGet(hash); if (state == null) { return; } List <UInt256> hashes = new List <UInt256>(); for (uint i = 1; i <= InvPayload.MaxHashesCount; i++) { uint index = state.TrimmedBlock.Index + i; if (index > blockchain.Height) { break; } hash = blockchain.GetBlockHash(index); if (hash == null) { break; } hashes.Add(hash); } if (hashes.Count == 0) { return; } Context.Parent.Tell(Message.Create("inv", InvPayload.Create(InventoryType.Block, hashes.ToArray()))); }
private void OnBroadcastInvCommand(InventoryType type, UInt256[] payload) { OnBroadcastCommand(MessageCommand.Inv, InvPayload.Create(type, payload)); }
internal async Task RelayAsync(Inventory data) { await SendMessageAsync("inv", InvPayload.Create(data.InventoryType, data.Hash)); }
private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest message) { if (context.State.HasFlag(ConsensusState.RequestReceived)) { return; } if (payload.ValidatorIndex != context.PrimaryIndex) { return; } Log($"{nameof(OnPrepareRequestReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} tx={message.TransactionHashes.Length}"); if (!context.State.HasFlag(ConsensusState.Backup)) { return; } if (payload.Timestamp <= context.PrevHeader.Timestamp || payload.Timestamp > TimeProvider.Current.UtcNow.AddMinutes(10).ToTimestamp()) { Log($"Timestamp incorrect: {payload.Timestamp}", LogLevel.Warning); return; } if (message.TransactionHashes.Any(p => context.TransactionExists(p))) { Log($"Invalid request: transaction already exists", LogLevel.Warning); return; } context.State |= ConsensusState.RequestReceived; context.Timestamp = payload.Timestamp; context.Nonce = message.Nonce; context.NextConsensus = message.NextConsensus; context.TransactionHashes = message.TransactionHashes; context.Transactions = new Dictionary <UInt256, Transaction>(); byte[] hashData = context.MakeHeader().GetHashData(); if (!Crypto.Default.VerifySignature(hashData, message.Signature, context.Validators[payload.ValidatorIndex].EncodePoint(false))) { return; } for (int i = 0; i < context.Signatures.Length; i++) { if (context.Signatures[i] != null) { if (!Crypto.Default.VerifySignature(hashData, context.Signatures[i], context.Validators[i].EncodePoint(false))) { context.Signatures[i] = null; } } } context.Signatures[payload.ValidatorIndex] = message.Signature; Dictionary <UInt256, Transaction> mempoolVerified = Blockchain.Singleton.MemPool.GetVerifiedTransactions().ToDictionary(p => p.Hash); List <Transaction> unverified = new List <Transaction>(); foreach (UInt256 hash in context.TransactionHashes.Skip(1)) { if (mempoolVerified.TryGetValue(hash, out Transaction tx)) { if (!AddTransaction(tx, false)) { return; } } else { if (Blockchain.Singleton.MemPool.TryGetValue(hash, out tx)) { unverified.Add(tx); } } } foreach (Transaction tx in unverified) { if (!AddTransaction(tx, true)) { return; } } if (!AddTransaction(message.MinerTransaction, true)) { return; } if (context.Transactions.Count < context.TransactionHashes.Length) { UInt256[] hashes = context.TransactionHashes.Where(i => !context.Transactions.ContainsKey(i)).ToArray(); taskManager.Tell(new TaskManager.RestartTasks { Payload = InvPayload.Create(InventoryType.TX, hashes) }); } }