Exemplo n.º 1
0
        public ConsensusPayload MakeRecoveryMessage()
        {
            PrepareRequest prepareRequestMessage = null;

            if (TransactionHashes != null)
            {
                prepareRequestMessage = new PrepareRequest
                {
                    ViewNumber        = ViewNumber,
                    TransactionHashes = TransactionHashes,
                    Nonce             = Nonce,
                    NextConsensus     = NextConsensus,
                    MinerTransaction  = (MinerTransaction)Transactions[TransactionHashes[0]],
                    Timestamp         = Timestamp
                };
            }
            return(MakeSignedPayload(new RecoveryMessage()
            {
                ChangeViewMessages = LastChangeViewPayloads.Where(p => p != null).Select(p => RecoveryMessage.ChangeViewPayloadCompact.FromPayload(p)).Take(this.M()).ToDictionary(p => (int)p.ValidatorIndex),
                PrepareRequestMessage = prepareRequestMessage,
                // We only need a PreparationHash set if we don't have the PrepareRequest information.
                PreparationHash = TransactionHashes == null ? PreparationPayloads.Where(p => p != null).GroupBy(p => p.GetDeserializedMessage <PrepareResponse>().PreparationHash, (k, g) => new { Hash = k, Count = g.Count() }).OrderByDescending(p => p.Count).Select(p => p.Hash).FirstOrDefault() : null,
                PreparationMessages = PreparationPayloads.Where(p => p != null).Select(p => RecoveryMessage.PreparationPayloadCompact.FromPayload(p)).ToDictionary(p => (int)p.ValidatorIndex),
                CommitMessages = this.CommitSent()
                    ? CommitPayloads.Where(p => p != null).Select(p => RecoveryMessage.CommitPayloadCompact.FromPayload(p)).ToDictionary(p => (int)p.ValidatorIndex)
                    : new Dictionary <int, RecoveryMessage.CommitPayloadCompact>()
            }));
        }
Exemplo n.º 2
0
        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 <= Blockchain.Default.GetHeader(context.PrevHash).Timestamp || payload.Timestamp > DateTime.Now.AddMinutes(10).ToTimestamp())
            {
                Log($"Timestamp incorrect: {payload.Timestamp}");
                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 = 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))
                    {
                        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();
                LocalNode.AllowHashes(hashes);
                InvPayload msg = InvPayload.Create(InventoryType.TX, hashes);
                foreach (RemoteNode node in localNode.GetRemoteNodes())
                {
                    node.EnqueueMessage("getdata", msg);
                }
            }
        }
Exemplo n.º 3
0
        public override void Deserialize(BinaryReader reader)
        {
            base.Deserialize(reader);
            ChangeViewMessages = reader.ReadSerializableArray <ChangeViewPayloadCompact>(Blockchain.MaxValidators).ToDictionary(p => (int)p.ValidatorIndex);
            if (reader.ReadBoolean())
            {
                PrepareRequestMessage = reader.ReadSerializable <PrepareRequest>();
            }
            else
            {
                int preparationHashSize = UInt256.Zero.Size;
                if (preparationHashSize == (int)reader.ReadVarInt((ulong)preparationHashSize))
                {
                    PreparationHash = new UInt256(reader.ReadBytes(preparationHashSize));
                }
            }

            PreparationMessages = reader.ReadSerializableArray <PreparationPayloadCompact>(Blockchain.MaxValidators).ToDictionary(p => (int)p.ValidatorIndex);
            CommitMessages      = reader.ReadSerializableArray <CommitPayloadCompact>(Blockchain.MaxValidators).ToDictionary(p => (int)p.ValidatorIndex);
        }
Exemplo n.º 4
0
        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> mempool = Blockchain.Singleton.GetMemoryPool().ToDictionary(p => p.Hash);
            List <Transaction> unverified             = new List <Transaction>();

            foreach (UInt256 hash in context.TransactionHashes.Skip(1))
            {
                if (mempool.TryGetValue(hash, out Transaction tx))
                {
                    if (!AddTransaction(tx, false))
                    {
                        return;
                    }
                }
                else
                {
                    tx = Blockchain.Singleton.GetUnverifiedTransaction(hash);
                    if (tx != null)
                    {
                        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)
                });
            }
        }