private static ConsensusPayload MakeSignedPayload(ConsensusContext context, ConsensusMessage message, ushort validatorIndex, byte[] witnessInvocationScript) { return(new ConsensusPayload { Version = context.Block.Version, PrevHash = context.Block.PrevHash, BlockIndex = context.Block.Index, ValidatorIndex = validatorIndex, ConsensusMessage = message, Witness = new Witness { InvocationScript = witnessInvocationScript, VerificationScript = Contract.CreateSignatureRedeemScript(context.Validators[validatorIndex]) } }); }
public async virtual Task ProcessMessageAsync(ConsensusMessage msg) { //_log.LogInformation($"ProcessMessage {msg.MsgType} _state is null? {!IsStateCreated()}"); if (msg is AuthorizingMsg || msg is ViewChangeRequestMessage) { await InternalProcessMessageAsync(msg); if (IsStateCreated()) { await ProcessQueueAsync(); } } else if (!IsStateCreated()) { _outOfOrderedMessages.Enqueue(msg); } else { await InternalProcessMessageAsync(msg); await ProcessQueueAsync(); } }
public MessageEnvelope(ConsensusMessage msg, int validatorIndex) { ExternalMessage = msg; InternalMessage = null; ValidatorIndex = validatorIndex; }
private void LocalNode_NewInventory(object sender, Inventory inventory) { ConsensusPayload payload = inventory as ConsensusPayload; if (payload != null) { lock (context) { if (payload.MinerIndex == context.MinerIndex) { return; } if (payload.Version != ConsensusContext.Version || payload.PrevHash != context.PrevHash || payload.Height != context.Height) { return; } if (payload.MinerIndex >= context.Miners.Length) { return; } ConsensusMessage message = ConsensusMessage.DeserializeFrom(payload.Data); if (message.ViewNumber != context.ViewNumber && message.Type != ConsensusMessageType.ChangeView) { return; } switch (message.Type) { case ConsensusMessageType.ChangeView: OnChangeViewReceived(payload, (ChangeView)message); break; case ConsensusMessageType.PerpareRequest: OnPerpareRequestReceived(payload, (PerpareRequest)message); break; case ConsensusMessageType.PerpareResponse: OnPerpareResponseReceived(payload, (PerpareResponse)message); break; } } } Transaction tx = inventory as Transaction; if (tx != null) { lock (context) { if (!context.State.HasFlag(ConsensusState.Backup) || !context.State.HasFlag(ConsensusState.RequestReceived) || context.State.HasFlag(ConsensusState.SignatureSent)) { return; } if (context.Transactions.ContainsKey(tx.Hash)) { return; } if (!context.TransactionHashes.Contains(tx.Hash)) { return; } AddTransaction(tx); } } }
public NetworkMessage ConsensusMessage(ConsensusMessage message) { return(new NetworkMessage { ConsensusMessage = message }); }
// Some protocols may stop due to null value in some of fields in the message. We discard such cases private bool ValidateMessage(ConsensusMessage message) { switch (message.PayloadCase) { case ConsensusMessage.PayloadOneofCase.Bval: // all fields have default values return(true); case ConsensusMessage.PayloadOneofCase.Aux: // all fields have default values return(true); case ConsensusMessage.PayloadOneofCase.Conf: // all fields have default values return(true); case ConsensusMessage.PayloadOneofCase.Coin: // all fields have default values return(true); case ConsensusMessage.PayloadOneofCase.Decrypted: // all fields have default values return(true); case ConsensusMessage.PayloadOneofCase.ValMessage: // merkleTreeRoot cannot be null if (message.ValMessage.MerkleTreeRoot is null) { return(false); } return(true); case ConsensusMessage.PayloadOneofCase.EchoMessage: // merkleTreeRoot cannot be null if (message.EchoMessage.MerkleTreeRoot is null) { return(false); } return(true); case ConsensusMessage.PayloadOneofCase.ReadyMessage: // merkleTreeRoot cannot be null if (message.ReadyMessage.MerkleTreeRoot is null) { return(false); } return(true); case ConsensusMessage.PayloadOneofCase.SignedHeaderMessage: // BlockHeader or Signature cannot be null var header = message.SignedHeaderMessage.Header; if (header is null || message.SignedHeaderMessage.Signature is null) { return(false); } // Check fields of BlockHeader: UInt256 cannot be null if (header.MerkleRoot is null || header.PrevBlockHash is null || header.StateHash is null) { return(false); } return(true); default: return(false); } }
public void Dispatch(ConsensusMessage message, int from) { if (_terminated) { Logger.LogTrace($"Era {_era} is already finished, skipping Dispatch"); return; } if (message.Validator.Era != _era) { throw new InvalidOperationException( $"Message for era {message.Validator.Era} dispatched to era {_era}"); } if (!ValidateMessage(message)) { Logger.LogWarning( $"Faulty behaviour: null value in required field of the consensus message from validator: {from}" + $" ({GetPublicKeyById(from)!.ToHex()}). Discarding message as it could crash targeted protocol."); return; } switch (message.PayloadCase) { case ConsensusMessage.PayloadOneofCase.Bval: var idBval = new BinaryBroadcastId(message.Validator.Era, message.Bval.Agreement, message.Bval.Epoch); EnsureProtocol(idBval)?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.Aux: var idAux = new BinaryBroadcastId(message.Validator.Era, message.Aux.Agreement, message.Aux.Epoch); EnsureProtocol(idAux)?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.Conf: var idConf = new BinaryBroadcastId(message.Validator.Era, message.Conf.Agreement, message.Conf.Epoch); EnsureProtocol(idConf)?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.Coin: var idCoin = new CoinId(message.Validator.Era, message.Coin.Agreement, message.Coin.Epoch); EnsureProtocol(idCoin)?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.Decrypted: var hbbftId = new HoneyBadgerId((int)message.Validator.Era); EnsureProtocol(hbbftId)?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.ValMessage: var reliableBroadcastId = new ReliableBroadcastId(message.ValMessage.SenderId, (int)message.Validator.Era); EnsureProtocol(reliableBroadcastId)?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.EchoMessage: var rbIdEchoMsg = new ReliableBroadcastId(message.EchoMessage.SenderId, (int)message.Validator.Era); EnsureProtocol(rbIdEchoMsg)?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.ReadyMessage: var rbIdReadyMsg = new ReliableBroadcastId(message.ReadyMessage.SenderId, (int)message.Validator.Era); EnsureProtocol(rbIdReadyMsg)?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.SignedHeaderMessage: var rootId = new RootProtocolId(message.Validator.Era); EnsureProtocol(rootId)?.ReceiveMessage(new MessageEnvelope(message, from)); break; default: throw new InvalidOperationException($"Unknown message type {message}"); } }
public void ConsensusService_Primary_Sends_PrepareRequest_After_OnStart() { TestProbe subscriber = CreateTestProbe(); var mockConsensusContext = new Mock <IConsensusContext>(); // context.Reset(): do nothing //mockConsensusContext.Setup(mr => mr.Reset()).Verifiable(); // void mockConsensusContext.SetupGet(mr => mr.MyIndex).Returns(2); // MyIndex == 2 mockConsensusContext.SetupGet(mr => mr.BlockIndex).Returns(2); mockConsensusContext.SetupGet(mr => mr.PrimaryIndex).Returns(2); mockConsensusContext.SetupGet(mr => mr.ViewNumber).Returns(0); mockConsensusContext.SetupProperty(mr => mr.Nonce); mockConsensusContext.SetupProperty(mr => mr.NextConsensus); mockConsensusContext.Object.NextConsensus = UInt160.Zero; mockConsensusContext.Setup(mr => mr.GetPrimaryIndex(It.IsAny <byte>())).Returns(2); mockConsensusContext.SetupProperty(mr => mr.State); // allows get and set to update mock state on Initialize method mockConsensusContext.Object.State = ConsensusState.Initial; int timeIndex = 0; var timeValues = new[] { new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc), // For tests here new DateTime(1968, 06, 01, 0, 0, 1, DateTimeKind.Utc), // For receiving block new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc), // For Initialize new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc), // unused new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc) // unused }; Console.WriteLine($"time 0: {timeValues[0].ToString()} 1: {timeValues[1].ToString()} 2: {timeValues[2].ToString()} 3: {timeValues[3].ToString()}"); //mockConsensusContext.Object.block_received_time = new DateTime(1968, 06, 01, 0, 0, 1, DateTimeKind.Utc); //mockConsensusContext.Setup(mr => mr.GetUtcNow()).Returns(new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc)); var timeMock = new Mock <TimeProvider>(); timeMock.SetupGet(tp => tp.UtcNow).Returns(() => timeValues[timeIndex]) .Callback(() => timeIndex++); //new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc)); TimeProvider.Current = timeMock.Object; //public void Log(string message, LogLevel level) // TODO: create ILogPlugin for Tests /* * mockConsensusContext.Setup(mr => mr.Log(It.IsAny<string>(), It.IsAny<LogLevel>())) * .Callback((string message, LogLevel level) => { * Console.WriteLine($"CONSENSUS LOG: {message}"); * } * ); */ // Creating proposed block Header header = new Header(); TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out ulong consensusDataVal, out Witness scriptVal); header.Size.Should().Be(109); Console.WriteLine($"header {header} hash {header.Hash} timstamp {timestampVal}"); timestampVal.Should().Be(4244941696); //1968-06-01 00:00:00 TimeProvider.Current.UtcNow.ToTimestamp().Should().Be(4244941711); //1968-06-01 00:00:15 // check basic ConsensusContext mockConsensusContext.Object.MyIndex.Should().Be(2); //mockConsensusContext.Object.block_received_time.ToTimestamp().Should().Be(4244941697); //1968-06-01 00:00:01 MinerTransaction minerTx = new MinerTransaction { Attributes = new TransactionAttribute[0], Inputs = new CoinReference[0], Outputs = new TransactionOutput[0], Witnesses = new Witness[0], Nonce = 42 }; PrepareRequest prep = new PrepareRequest { Nonce = mockConsensusContext.Object.Nonce, NextConsensus = mockConsensusContext.Object.NextConsensus, TransactionHashes = new UInt256[0], MinerTransaction = minerTx, //(MinerTransaction)Transactions[TransactionHashes[0]], Signature = new byte[64] //Signatures[MyIndex] }; ConsensusMessage mprep = prep; byte[] prepData = mprep.ToArray(); ConsensusPayload prepPayload = new ConsensusPayload { Version = 0, PrevHash = mockConsensusContext.Object.PrevHash, BlockIndex = mockConsensusContext.Object.BlockIndex, ValidatorIndex = (ushort)mockConsensusContext.Object.MyIndex, Timestamp = mockConsensusContext.Object.Timestamp, Data = prepData }; mockConsensusContext.Setup(mr => mr.MakePrepareRequest()).Returns(prepPayload); // ============================================================================ // creating ConsensusService actor // ============================================================================ TestActorRef <ConsensusService> actorConsensus = ActorOfAsTestActorRef <ConsensusService>( Akka.Actor.Props.Create(() => new ConsensusService(subscriber, subscriber, mockConsensusContext.Object)) ); Console.WriteLine("will trigger OnPersistCompleted!"); actorConsensus.Tell(new Blockchain.PersistCompleted { Block = new Block { Version = header.Version, PrevHash = header.PrevHash, MerkleRoot = header.MerkleRoot, Timestamp = header.Timestamp, Index = header.Index, ConsensusData = header.ConsensusData, NextConsensus = header.NextConsensus } }); //Console.WriteLine("will start consensus!"); //actorConsensus.Tell(new ConsensusService.Start()); Console.WriteLine("OnTimer should expire!"); Console.WriteLine("Waiting for subscriber message!"); var answer = subscriber.ExpectMsg <LocalNode.SendDirectly>(); Console.WriteLine($"MESSAGE 1: {answer}"); //var answer2 = subscriber.ExpectMsg<LocalNode.SendDirectly>(); // expects to fail! // ============================================================================ // finalize ConsensusService actor // ============================================================================ //Thread.Sleep(4000); Sys.Stop(actorConsensus); TimeProvider.ResetToDefault(); Assert.AreEqual(1, 1); }
public void Dispatch(ConsensusMessage message, int from) { if (_silenced.Contains(from)) { return; } if (_silenced.Contains(GetMyId())) { return; } switch (message.PayloadCase) { case ConsensusMessage.PayloadOneofCase.Bval: var idBval = new BinaryBroadcastId(message.Validator.Era, message.Bval.Agreement, message.Bval.Epoch); CheckRequest(idBval); Registry[idBval]?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.Aux: var idAux = new BinaryBroadcastId(message.Validator.Era, message.Aux.Agreement, message.Aux.Epoch); CheckRequest(idAux); Registry[idAux]?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.Conf: var idConf = new BinaryBroadcastId(message.Validator.Era, message.Conf.Agreement, message.Conf.Epoch); CheckRequest(idConf); Registry[idConf]?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.Coin: var idCoin = new CoinId(message.Validator.Era, message.Coin.Agreement, message.Coin.Epoch); CheckRequest(idCoin); Registry[idCoin]?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.Decrypted: var hbbftId = new HoneyBadgerId((int)message.Validator.Era); CheckRequest(hbbftId); Registry[hbbftId]?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.ReadyMessage: var rbIdReadyMsg = new ReliableBroadcastId(message.ReadyMessage.SenderId, (int)message.Validator.Era); CheckRequest(rbIdReadyMsg); Registry[rbIdReadyMsg]?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.ValMessage: var reliableBroadcastId = new ReliableBroadcastId(message.ValMessage.SenderId, (int)message.Validator.Era); CheckRequest(reliableBroadcastId); Registry[reliableBroadcastId]?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.EchoMessage: var rbIdEchoMsg = new ReliableBroadcastId(message.EchoMessage.SenderId, (int)message.Validator.Era); CheckRequest(rbIdEchoMsg); Registry[rbIdEchoMsg]?.ReceiveMessage(new MessageEnvelope(message, from)); break; case ConsensusMessage.PayloadOneofCase.SignedHeaderMessage: var idRoot = new RootProtocolId(message.Validator.Era); CheckRequest(idRoot); Registry[idRoot]?.ReceiveMessage(new MessageEnvelope(message, from)); break; default: throw new InvalidOperationException($"Unknown message type {message.PayloadCase}"); } }
protected virtual Task InternalProcessMessageAsync(ConsensusMessage msg) { throw new InvalidOperationException("Must override."); }